Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-10-11 21:10:14 +00:00
parent 6e7be08ca5
commit 3ecbefc581
43 changed files with 103 additions and 123 deletions

View file

@ -55,6 +55,7 @@ workflow:
RUBY_VERSION: "3.0"
NOTIFY_PIPELINE_FAILURE_CHANNEL: "f_ruby3"
OMNIBUS_GITLAB_RUBY3_BUILD: "true"
OMNIBUS_GITLAB_CACHE_EDITION: "GITLAB_RUBY3"
# For `$CI_DEFAULT_BRANCH` branch, create a pipeline (this includes on schedules, pushes, merges, etc.).
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
# For tags, create a pipeline.

View file

@ -46,6 +46,7 @@ stages:
echo "OMNIBUS_GITLAB_CACHE_UPDATE=${OMNIBUS_GITLAB_CACHE_UPDATE:-false}" >> $BUILD_ENV
for version_file in *_VERSION; do echo "$version_file=$(cat $version_file)" >> $BUILD_ENV; done
echo "OMNIBUS_GITLAB_RUBY3_BUILD=${OMNIBUS_GITLAB_RUBY3_BUILD:-false}" >> $BUILD_ENV
echo "OMNIBUS_GITLAB_CACHE_EDITION=${OMNIBUS_GITLAB_CACHE_EDITION:-GITLAB}" >> $BUILD_ENV
echo "Built environment file for omnibus build:"
cat $BUILD_ENV
artifacts:
@ -130,6 +131,7 @@ trigger-omnibus:
SECURITY_SOURCES: $SECURITY_SOURCES
CACHE_UPDATE: $OMNIBUS_GITLAB_CACHE_UPDATE
RUBY3_BUILD: $OMNIBUS_GITLAB_RUBY3_BUILD
CACHE_EDITION: $OMNIBUS_GITLAB_CACHE_EDITION
SKIP_QA_DOCKER: "true"
SKIP_QA_TEST: "true"
ee: "true"

View file

@ -4,6 +4,7 @@ variables:
SKIP_REPORT_IN_ISSUES: "true"
OMNIBUS_GITLAB_CACHE_UPDATE: "false"
OMNIBUS_GITLAB_RUBY3_BUILD: "false"
OMNIBUS_GITLAB_CACHE_EDITION: "GITLAB"
QA_LOG_LEVEL: "info"
QA_TESTS: ""
QA_FEATURE_FLAGS: ""

View file

@ -1,9 +0,0 @@
query sidebarDetails($fullPath: ID!, $iid: String!) {
project(fullPath: $fullPath) {
id
issue(iid: $iid) {
id
iid
}
}
}

View file

@ -1,9 +0,0 @@
query mergeRequestSidebarDetails($fullPath: ID!, $iid: String!) {
project(fullPath: $fullPath) {
id
mergeRequest(iid: $iid) {
id
iid # currently unused.
}
}
}

View file

@ -1,15 +1,8 @@
import sidebarDetailsIssueQuery from 'ee_else_ce/sidebar/queries/sidebar_details.query.graphql';
import { TYPE_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
import axios from '~/lib/utils/axios_utils';
import reviewerRereviewMutation from '../queries/reviewer_rereview.mutation.graphql';
import sidebarDetailsMRQuery from '../queries/sidebar_details_mr.query.graphql';
const queries = {
merge_request: sidebarDetailsMRQuery,
issue: sidebarDetailsIssueQuery,
};
export const gqClient = createGqClient(
{},
@ -36,37 +29,13 @@ export default class SidebarService {
}
get() {
return Promise.all([
axios.get(this.endpoint),
gqClient.query({
query: this.sidebarDetailsQuery(),
variables: {
fullPath: this.fullPath,
iid: this.iid.toString(),
},
}),
]);
}
sidebarDetailsQuery() {
return queries[this.issuableType];
return axios.get(this.endpoint);
}
update(key, data) {
return axios.put(this.endpoint, { [key]: data });
}
updateWithGraphQl(mutation, variables) {
return gqClient.mutate({
mutation,
variables: {
...variables,
projectPath: this.fullPath,
iid: this.iid.toString(),
},
});
}
getProjectsAutocomplete(searchTerm) {
return axios.get(this.projectsAutocompleteEndpoint, {
params: {

View file

@ -93,8 +93,8 @@ export default class SidebarMediator {
fetch() {
return this.service
.get()
.then(([restResponse, graphQlResponse]) => {
this.processFetchedData(restResponse.data, graphQlResponse.data);
.then(({ data }) => {
this.processFetchedData(data);
})
.catch(() =>
createAlert({

View file

@ -54,10 +54,6 @@ strong {
font-weight: bold;
}
a {
color: $blue-600;
}
hr {
overflow: hidden;
}

View file

@ -33,14 +33,6 @@
}
}
a {
color: $blue-600;
> code {
color: $blue-600;
}
}
.media-container {
display: inline-flex;
flex-direction: column;

View file

@ -382,6 +382,8 @@ $gl-text-color-quaternary: #d6d6d6;
$gl-text-color-inverted: $white;
$gl-text-color-secondary-inverted: rgba($white, 0.85);
$gl-text-color-disabled: $gray-400;
$link-color: $blue-500 !default;
$link-hover-color: $blue-500 !default;
$gl-grayish-blue: #7f8fa4;
$gl-header-color: #4c4e54;
$gl-font-size-12: 12px;

View file

@ -57,7 +57,7 @@ strong {
font-weight: bolder;
}
a {
color: #007bff;
color: #428fdc;
text-decoration: none;
background-color: transparent;
}
@ -569,9 +569,6 @@ html [type="button"],
strong {
font-weight: bold;
}
a {
color: #63a6e9;
}
svg {
vertical-align: baseline;
}

View file

@ -38,7 +38,7 @@ strong {
font-weight: bolder;
}
a {
color: #007bff;
color: #1f75cb;
text-decoration: none;
background-color: transparent;
}
@ -550,9 +550,6 @@ html [type="button"],
strong {
font-weight: bold;
}
a {
color: #1068bf;
}
svg {
vertical-align: baseline;
}

View file

@ -41,7 +41,7 @@ p {
margin-bottom: 1rem;
}
a {
color: #007bff;
color: #1f75cb;
text-decoration: none;
background-color: transparent;
}
@ -595,9 +595,6 @@ h3 {
margin-top: 20px;
margin-bottom: 10px;
}
a {
color: #1068bf;
}
hr {
overflow: hidden;
}

View file

@ -195,6 +195,8 @@ module Members
end
def publish_event!
return unless member_created_namespace_id
Gitlab::EventStore.publish(
Members::MembersAddedEvent.new(data: {
source_id: source.id,

View file

@ -80,9 +80,9 @@ GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab
## Upgrading to GitLab 14.0/14.1
### Primary sites can not be removed from the UI
### Primary sites cannot be removed from the UI
We found an issue where [Primary sites can not be removed from the UI](https://gitlab.com/gitlab-org/gitlab/-/issues/338231).
We found an issue where [Primary sites cannot be removed from the UI](https://gitlab.com/gitlab-org/gitlab/-/issues/338231).
This bug only exists in the UI and does not block the removal of Primary sites using any other method.

View file

@ -1123,7 +1123,7 @@ postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
### Reinitialize a replica
If a replica cannot start or rejoin the cluster, or when it lags behind and can not catch up, it might be necessary to reinitialize the replica:
If a replica cannot start or rejoin the cluster, or when it lags behind and cannot catch up, it might be necessary to reinitialize the replica:
1. [Check the replication status](#check-replication-status) to confirm which server
needs to be reinitialized. For example:

View file

@ -306,7 +306,7 @@ end
### Remove Sidekiq jobs for given parameters (destructive)
The general method to kill jobs conditionally is the following command, which
removes jobs that are queued but not started. Running jobs can not be killed.
removes jobs that are queued but not started. Running jobs cannot be killed.
```ruby
queue = Sidekiq::Queue.new('<queue name>')

View file

@ -317,7 +317,7 @@ with its `partition_id`, and we will be able to find the partition that the
pipeline data is stored in.
We will need to constrain access to searching through pipelines, builds,
artifacts etc. Search can not be done through all partitions, as it would not
artifacts etc. Search cannot be done through all partitions, as it would not
be efficient enough, hence we will need to find a better way of searching
through archived pipelines data. It will be necessary to have different access
patterns to access archived data in the UI and API.
@ -343,7 +343,7 @@ has_many :builds, -> (pipeline) { where(partition_id: pipeline.partition_id) }
```
The problem with this approach is that it makes preloading much more difficult
as instance dependent associations can not be used with preloads:
as instance dependent associations cannot be used with preloads:
```plaintext
ArgumentError: The association scope 'builds' is instance dependent (the

View file

@ -27,7 +27,7 @@ application.
Let's first consider entities with no inherent time-related bias for their data.
A record for a user or a project may be equally important and frequently accessed, irrelevant to when
it was created. We can not predict by using a user's `id` or `created_at` how often the related
it was created. We cannot predict by using a user's `id` or `created_at` how often the related
record is accessed or updated.
On the other hand, a good example for datasets with extreme time-decay effects are logs and time
@ -91,7 +91,7 @@ a maximum of a month of events, restricted to 6 months in the past.
### Immutability
The third characteristic of time-decay data is that their **time-decay status does not change**.
Once they are considered "old", they can not switch back to "new" or relevant again.
Once they are considered "old", they cannot switch back to "new" or relevant again.
This definition may sound trivial, but we have to be able to make operations over "old" data **more**
expensive (for example, by archiving or moving them to less expensive storage) without having to worry about

View file

@ -198,7 +198,7 @@ To make a runner pick untagged jobs:
1. Select **Save changes** for the changes to take effect.
NOTE:
The runner tags list can not be empty when it's not allowed to pick untagged jobs.
The runner tags list cannot be empty when it's not allowed to pick untagged jobs.
Below are some example scenarios of different variations.

View file

@ -57,5 +57,6 @@ Each image is running a specific version of macOS and Xcode.
| `macos-10.14-xcode-10` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/mojave.yml> |
| `macos-10.15-xcode-11` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/catalina.yml> |
| `macos-11-xcode-12` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/big-sur.yml> |
| `macos-12-xcode-13` | `maintenance` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/monterey.yml> |
| `macos-12-xcode-13` | `maintenance` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/monterey.yml> |
| `macos-12-xcode-14` | `maintenance` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/monterey.yml> |
| (none, awaiting macOS 13) | `beta` | |

View file

@ -52,7 +52,7 @@ and they serve us and our users well. Some examples of these principles are that
- The feedback delivered by GitLab CI/CD and data produced by the platform should be accurate.
If a job fails and we notify a user that it was successful, it can have severe negative consequences.
- Feedback needs to be available when a user needs it and data can not disappear unexpectedly when engineers need it.
- Feedback needs to be available when a user needs it and data cannot disappear unexpectedly when engineers need it.
- It all doesn't matter if the platform is not secure and we
are leaking credentials or secrets.
- When a user provides a set of preconditions in a form of CI/CD configuration, the result should be deterministic each time a pipeline runs, because otherwise the platform might not be trustworthy.
@ -62,7 +62,7 @@ are leaking credentials or secrets.
### Measure before you optimize, and make data-informed decisions
It is very difficult to optimize something that you can not measure. How would you
It is very difficult to optimize something that you cannot measure. How would you
know if you succeeded, or how significant the success was? If you are working on
a performance or reliability improvement, make sure that you measure things before
you optimize them.

View file

@ -44,7 +44,7 @@ into this category.
## Isolation
Background migrations must be isolated and can not use application code (for example,
Background migrations must be isolated and cannot use application code (for example,
models defined in `app/models` except the `ApplicationRecord` classes). Since these migrations
can take a long time to run it's possible for new versions to be deployed while they are still running.

View file

@ -41,7 +41,7 @@ into this category.
## Isolation
Batched background migrations must be isolated and can not use application code (for example,
Batched background migrations must be isolated and cannot use application code (for example,
models defined in `app/models` except the `ApplicationRecord` classes).
Because these migrations can take a long time to run, it's possible
for new versions to deploy while the migrations are still running.

View file

@ -93,7 +93,7 @@ We only want to enforce the `NOT NULL` constraint without setting a default, as
that all epics should have a user-generated description.
After checking our production database, we know that there are `epics` with `NULL` descriptions,
so we can not add and validate the constraint in one step.
so we cannot add and validate the constraint in one step.
NOTE:
Even if we did not have any epic with a `NULL` description, another instance of GitLab could have

View file

@ -15,7 +15,7 @@ When adding new columns to store strings or other textual information:
the `#text ... limit: 100` helper (see below) when creating a table, or by using the `add_text_limit`
when altering an existing table.
The standard Rails `text` column type can not be defined with a limit, but we extend `create_table` to
The standard Rails `text` column type cannot be defined with a limit, but we extend `create_table` to
add a `limit: 255` option. Outside of `create_table`, `add_text_limit` can be used to add a [check constraint](https://www.postgresql.org/docs/11/ddl-constraints.html)
to an already existing column.
@ -131,7 +131,7 @@ Issues is a pretty busy and large table with more than 25 million rows, so we do
other processes that try to access it while running the update.
Also, after checking our production database, we know that there are `issues` with more characters in
their title than the 1024 character limit, so we can not add and validate the constraint in one step.
their title than the 1024 character limit, so we cannot add and validate the constraint in one step.
NOTE:
Even if we did not have any record with a title larger than the provided limit, another

View file

@ -546,7 +546,7 @@ improve this query, other than _not_ running it at all.
What is important here is that while some may recommend to straight up add an
index the moment you see a sequential scan, it is _much more important_ to first
understand what your query does, how much data it retrieves, and so on. After
all, you can not optimize something you do not understand.
all, you cannot optimize something you do not understand.
### Cardinality and selectivity

View file

@ -16,6 +16,6 @@ The main purpose is for support. Per the website:
> creator and maintainer. Get prioritized support for issues and requests.
Note that we **cannot** use the Pro version directly in our product, since we are
an Open Core product - we can not require customers to purchase the Pro version, nor can we ship it.
an Open Core product - we cannot require customers to purchase the Pro version, nor can we ship it.
Details on the billing account and gem licensing can be found in the Engineering 1Password vault.

View file

@ -111,7 +111,7 @@ The specified project export file in `archive_path` is missing.
##### `Exception: Permission denied @ rb_sysopen - (filename)`
The specified project export file can not be accessed by the `git` user.
The specified project export file cannot be accessed by the `git` user.
Setting the file owner to `git:git`, changing the file permissions to `0400`, and moving it to a
public folder (for example `/tmp/`) fixes the issue.

View file

@ -7,7 +7,7 @@ type: reference, api
# Internal API **(FREE)**
The internal API is used by different GitLab components, it can not be
The internal API is used by different GitLab components, it cannot be
used by other consumers. This documentation is intended for people
working on the GitLab codebase.
@ -21,7 +21,7 @@ Before adding a new internal endpoint, consider if the API would potentially be
useful to the wider GitLab community and can be made externally accessible.
One reason we might favor internal API endpoints sometimes is when using such an endpoint requires
internal data that external actors can not have. For example, in the internal Pages API we might use
internal data that external actors cannot have. For example, in the internal Pages API we might use
a secret token that identifies a request as internal or sign a request with a public key that is
not available to a wider community.

View file

@ -42,7 +42,7 @@ issues or when linking objects of the type from Epics. It should use the same
- You can't close it from a commit or a merge request.
- You can't mark it as related to another issue.
If an Issue type can not be used you can still define a first-class type and
If an Issue type cannot be used you can still define a first-class type and
then include concerns such as `Issuable` or `Noteable` to reuse functionality
which is common for all our issue-related resources. But you still need to
define the interface for working with the new resource and update some other

View file

@ -37,7 +37,7 @@ Groups and projects can have the following visibility levels:
- private (`0`) - an entity is visible only to the approved members of the entity
By default, subgroups can **not** have higher visibility levels.
For example, if you create a new private group, it can not include a public subgroup.
For example, if you create a new private group, it cannot include a public subgroup.
The visibility level of a group can be changed only if all subgroups and
sub-projects have the same or lower visibility level. For example, a group can be set

View file

@ -244,7 +244,7 @@ Example output:
```
NOTE:
This endpoint is only available for Rails web workers. Sidekiq workers can not be inspected this way.
This endpoint is only available for Rails web workers. Sidekiq workers cannot be inspected this way.
## Settings that impact performance

View file

@ -96,7 +96,7 @@ This is just a sketch, but it shows the general idea: we would use whatever the
## End goal
The guidelines in this document are meant to foster _better_ code reuse, by
clearly defining what can be reused where, and what to do when you can not reuse
clearly defining what can be reused where, and what to do when you cannot reuse
something. Clearly separating abstractions makes it harder to use the wrong one,
makes it easier to debug the code, and (hopefully) results in fewer performance
problems.
@ -265,7 +265,7 @@ For example: `:job_not_retriable`, `:duplicate_package`, `:merge_request_not_mer
Everything in `app/finders`, typically used for retrieving data from a database.
Finders can not reuse other finders in an attempt to better control the SQL
Finders cannot reuse other finders in an attempt to better control the SQL
queries they produce.
Finders' `execute` method should return `ActiveRecord::Relation`. Exceptions

View file

@ -179,7 +179,7 @@ As the HyperLogLog algorithm is probabilistic, the **results always include erro
The highest encountered error rate is 4.9%.
When correctly used, the `estimate_batch_distinct_count` method enables efficient counting over
columns that contain non-unique values, which can not be assured by other counters.
columns that contain non-unique values, which cannot be assured by other counters.
##### estimate_batch_distinct_count method

View file

@ -190,7 +190,7 @@ You can override the default values in the `values.yaml` file in the
`HELM_UPGRADE_VALUES_FILE` [CI/CD variable](#cicd-variables) with
the path and name.
Some values can not be overridden with the options above. Settings like `replicaCount` should instead be overridden with the `REPLICAS`
Some values cannot be overridden with the options above. Settings like `replicaCount` should instead be overridden with the `REPLICAS`
[build and deployment](#build-and-deployment) CI/CD variable. Follow [this issue](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/issues/31) for more information.
NOTE:

View file

@ -61,7 +61,7 @@ token as the API key.
## Running Spamcheck over TLS
Spamcheck service on its own can not communicate directly over TLS with GitLab.
Spamcheck service on its own cannot communicate directly over TLS with GitLab.
However, Spamcheck can be deployed behind a reverse proxy which performs TLS
termination. In such a scenario, GitLab can be made to communicate with
Spamcheck over TLS by specifying `tls://` scheme for the external Spamcheck URL

View file

@ -480,7 +480,7 @@ When using `DAST_PATHS` and `DAST_PATHS_FILE`, note the following:
- `DAST_WEBSITE` must be defined when using either `DAST_PATHS_FILE` or `DAST_PATHS`. The paths listed in either use `DAST_WEBSITE` to build the URLs to scan
- Spidering is disabled when `DAST_PATHS` or `DAST_PATHS_FILE` are defined
- `DAST_PATHS_FILE` and `DAST_PATHS` can not be used together
- `DAST_PATHS_FILE` and `DAST_PATHS` cannot be used together
- The `DAST_PATHS` variable has a limit of about 130kb. If you have a list or paths
greater than this, use `DAST_PATHS_FILE`.

View file

@ -48,7 +48,7 @@ possible, we encourage you to use all of our security scanning tools:
then performs a build to fetch upstream dependency information. In the case of
containers, Dependency Scanning uses the compatible manifest and reports only these
declared software dependencies (and those installed as a sub-dependency).
Dependency Scanning can not detect software dependencies that are pre-bundled
Dependency Scanning cannot detect software dependencies that are pre-bundled
into the container's base image. To identify pre-bundled dependencies, enable
[Container Scanning](../container_scanning/index.md) language scanning using the
[`CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` variable](../container_scanning/index.md#report-language-specific-findings).

View file

@ -177,7 +177,7 @@ You can add an internal note **to an issue or an epic**. It's then visible only
Keep in mind:
- Replies to internal notes are also internal.
- You can not turn an internal note into a regular comment.
- You cannot turn an internal note into a regular comment.
Prerequisites:

View file

@ -19,7 +19,7 @@ if [ "$QA_SKIP_ALL_TESTS" == "true" ]; then
fi
# set custom cache key to override default cache in pipeline-common because we use bundle to install gitlab-qa gem
qa_cache_key="qa-e2e-$(md5sum qa/Gemfile.lock | awk '{ print $1 }')"
qa_cache_key="qa-e2e-ruby-${RUBY_VERSION}-$(md5sum qa/Gemfile.lock | awk '{ print $1 }')"
variables=$(cat <<YML
variables:
GITLAB_QA_CACHE_KEY: "$qa_cache_key"

View file

@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import * as urlUtility from '~/lib/utils/url_utility';
import SidebarService, { gqClient } from '~/sidebar/services/sidebar_service';
import SidebarService from '~/sidebar/services/sidebar_service';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
import Mock from './mock_data';
@ -42,22 +42,14 @@ describe('Sidebar mediator', () => {
});
});
it('fetches the data', () => {
it('fetches the data', async () => {
const mockData = Mock.responseMap.GET[mediatorMockData.endpoint];
mock.onGet(mediatorMockData.endpoint).reply(200, mockData);
const mockGraphQlData = Mock.graphQlResponseData;
const graphQlSpy = jest.spyOn(gqClient, 'query').mockReturnValue({
data: mockGraphQlData,
});
const spy = jest.spyOn(mediator, 'processFetchedData').mockReturnValue(Promise.resolve());
await mediator.fetch();
return mediator.fetch().then(() => {
expect(spy).toHaveBeenCalledWith(mockData, mockGraphQlData);
spy.mockRestore();
graphQlSpy.mockRestore();
});
expect(spy).toHaveBeenCalledWith(mockData);
spy.mockRestore();
});
it('processes fetched data', () => {

View file

@ -110,12 +110,61 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
expect(execute_service[:status]).to eq(:success)
end
end
context 'when only one user fails validations' do
let_it_be(:source) { create(:project, group: create(:group)) }
let(:user_id) { [member.id, user_invited_by_id.id] }
before do
# validations will fail because we try to invite them to the project as a guest
source.group.add_developer(member)
end
it 'triggers the members added event' do
expect(Gitlab::EventStore)
.to receive(:publish)
.with(an_instance_of(Members::MembersAddedEvent))
.and_call_original
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message])
.to include 'Access level should be greater than or equal to Developer inherited membership from group'
expect(source.users).not_to include(member)
expect(source.users).to include(user_invited_by_id)
end
end
context 'when all users fail validations' do
let_it_be(:source) { create(:project, group: create(:group)) }
let(:user_id) { [member.id, user_invited_by_id.id] }
before do
# validations will fail because we try to invite them to the project as a guest
source.group.add_developer(member)
source.group.add_developer(user_invited_by_id)
end
it 'does not trigger the members added event' do
expect(Gitlab::EventStore)
.not_to receive(:publish)
.with(an_instance_of(Members::MembersAddedEvent))
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message])
.to include 'Access level should be greater than or equal to Developer inherited membership from group'
expect(source.users).not_to include(member, user_invited_by_id)
end
end
end
context 'when passing no user ids' do
let(:user_id) { '' }
it 'does not add a member' do
expect(Gitlab::EventStore)
.not_to receive(:publish)
.with(an_instance_of(Members::MembersAddedEvent))
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to be_present
expect(source.users).not_to include member