Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
6e7be08ca5
commit
3ecbefc581
43 changed files with 103 additions and 123 deletions
|
@ -55,6 +55,7 @@ workflow:
|
||||||
RUBY_VERSION: "3.0"
|
RUBY_VERSION: "3.0"
|
||||||
NOTIFY_PIPELINE_FAILURE_CHANNEL: "f_ruby3"
|
NOTIFY_PIPELINE_FAILURE_CHANNEL: "f_ruby3"
|
||||||
OMNIBUS_GITLAB_RUBY3_BUILD: "true"
|
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.).
|
# For `$CI_DEFAULT_BRANCH` branch, create a pipeline (this includes on schedules, pushes, merges, etc.).
|
||||||
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
# For tags, create a pipeline.
|
# For tags, create a pipeline.
|
||||||
|
|
|
@ -46,6 +46,7 @@ stages:
|
||||||
echo "OMNIBUS_GITLAB_CACHE_UPDATE=${OMNIBUS_GITLAB_CACHE_UPDATE:-false}" >> $BUILD_ENV
|
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
|
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_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:"
|
echo "Built environment file for omnibus build:"
|
||||||
cat $BUILD_ENV
|
cat $BUILD_ENV
|
||||||
artifacts:
|
artifacts:
|
||||||
|
@ -130,6 +131,7 @@ trigger-omnibus:
|
||||||
SECURITY_SOURCES: $SECURITY_SOURCES
|
SECURITY_SOURCES: $SECURITY_SOURCES
|
||||||
CACHE_UPDATE: $OMNIBUS_GITLAB_CACHE_UPDATE
|
CACHE_UPDATE: $OMNIBUS_GITLAB_CACHE_UPDATE
|
||||||
RUBY3_BUILD: $OMNIBUS_GITLAB_RUBY3_BUILD
|
RUBY3_BUILD: $OMNIBUS_GITLAB_RUBY3_BUILD
|
||||||
|
CACHE_EDITION: $OMNIBUS_GITLAB_CACHE_EDITION
|
||||||
SKIP_QA_DOCKER: "true"
|
SKIP_QA_DOCKER: "true"
|
||||||
SKIP_QA_TEST: "true"
|
SKIP_QA_TEST: "true"
|
||||||
ee: "true"
|
ee: "true"
|
||||||
|
|
|
@ -4,6 +4,7 @@ variables:
|
||||||
SKIP_REPORT_IN_ISSUES: "true"
|
SKIP_REPORT_IN_ISSUES: "true"
|
||||||
OMNIBUS_GITLAB_CACHE_UPDATE: "false"
|
OMNIBUS_GITLAB_CACHE_UPDATE: "false"
|
||||||
OMNIBUS_GITLAB_RUBY3_BUILD: "false"
|
OMNIBUS_GITLAB_RUBY3_BUILD: "false"
|
||||||
|
OMNIBUS_GITLAB_CACHE_EDITION: "GITLAB"
|
||||||
QA_LOG_LEVEL: "info"
|
QA_LOG_LEVEL: "info"
|
||||||
QA_TESTS: ""
|
QA_TESTS: ""
|
||||||
QA_FEATURE_FLAGS: ""
|
QA_FEATURE_FLAGS: ""
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
query sidebarDetails($fullPath: ID!, $iid: String!) {
|
|
||||||
project(fullPath: $fullPath) {
|
|
||||||
id
|
|
||||||
issue(iid: $iid) {
|
|
||||||
id
|
|
||||||
iid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
query mergeRequestSidebarDetails($fullPath: ID!, $iid: String!) {
|
|
||||||
project(fullPath: $fullPath) {
|
|
||||||
id
|
|
||||||
mergeRequest(iid: $iid) {
|
|
||||||
id
|
|
||||||
iid # currently unused.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +1,8 @@
|
||||||
import sidebarDetailsIssueQuery from 'ee_else_ce/sidebar/queries/sidebar_details.query.graphql';
|
|
||||||
import { TYPE_USER } from '~/graphql_shared/constants';
|
import { TYPE_USER } from '~/graphql_shared/constants';
|
||||||
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
||||||
import createGqClient, { fetchPolicies } from '~/lib/graphql';
|
import createGqClient, { fetchPolicies } from '~/lib/graphql';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import reviewerRereviewMutation from '../queries/reviewer_rereview.mutation.graphql';
|
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(
|
export const gqClient = createGqClient(
|
||||||
{},
|
{},
|
||||||
|
@ -36,37 +29,13 @@ export default class SidebarService {
|
||||||
}
|
}
|
||||||
|
|
||||||
get() {
|
get() {
|
||||||
return Promise.all([
|
return axios.get(this.endpoint);
|
||||||
axios.get(this.endpoint),
|
|
||||||
gqClient.query({
|
|
||||||
query: this.sidebarDetailsQuery(),
|
|
||||||
variables: {
|
|
||||||
fullPath: this.fullPath,
|
|
||||||
iid: this.iid.toString(),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
sidebarDetailsQuery() {
|
|
||||||
return queries[this.issuableType];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update(key, data) {
|
update(key, data) {
|
||||||
return axios.put(this.endpoint, { [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) {
|
getProjectsAutocomplete(searchTerm) {
|
||||||
return axios.get(this.projectsAutocompleteEndpoint, {
|
return axios.get(this.projectsAutocompleteEndpoint, {
|
||||||
params: {
|
params: {
|
||||||
|
|
|
@ -93,8 +93,8 @@ export default class SidebarMediator {
|
||||||
fetch() {
|
fetch() {
|
||||||
return this.service
|
return this.service
|
||||||
.get()
|
.get()
|
||||||
.then(([restResponse, graphQlResponse]) => {
|
.then(({ data }) => {
|
||||||
this.processFetchedData(restResponse.data, graphQlResponse.data);
|
this.processFetchedData(data);
|
||||||
})
|
})
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
createAlert({
|
createAlert({
|
||||||
|
|
|
@ -54,10 +54,6 @@ strong {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
color: $blue-600;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,14 +33,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
color: $blue-600;
|
|
||||||
|
|
||||||
> code {
|
|
||||||
color: $blue-600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-container {
|
.media-container {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
@ -382,6 +382,8 @@ $gl-text-color-quaternary: #d6d6d6;
|
||||||
$gl-text-color-inverted: $white;
|
$gl-text-color-inverted: $white;
|
||||||
$gl-text-color-secondary-inverted: rgba($white, 0.85);
|
$gl-text-color-secondary-inverted: rgba($white, 0.85);
|
||||||
$gl-text-color-disabled: $gray-400;
|
$gl-text-color-disabled: $gray-400;
|
||||||
|
$link-color: $blue-500 !default;
|
||||||
|
$link-hover-color: $blue-500 !default;
|
||||||
$gl-grayish-blue: #7f8fa4;
|
$gl-grayish-blue: #7f8fa4;
|
||||||
$gl-header-color: #4c4e54;
|
$gl-header-color: #4c4e54;
|
||||||
$gl-font-size-12: 12px;
|
$gl-font-size-12: 12px;
|
||||||
|
|
|
@ -57,7 +57,7 @@ strong {
|
||||||
font-weight: bolder;
|
font-weight: bolder;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: #007bff;
|
color: #428fdc;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
@ -569,9 +569,6 @@ html [type="button"],
|
||||||
strong {
|
strong {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
a {
|
|
||||||
color: #63a6e9;
|
|
||||||
}
|
|
||||||
svg {
|
svg {
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ strong {
|
||||||
font-weight: bolder;
|
font-weight: bolder;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: #007bff;
|
color: #1f75cb;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
@ -550,9 +550,6 @@ html [type="button"],
|
||||||
strong {
|
strong {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
a {
|
|
||||||
color: #1068bf;
|
|
||||||
}
|
|
||||||
svg {
|
svg {
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: #007bff;
|
color: #1f75cb;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
@ -595,9 +595,6 @@ h3 {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
a {
|
|
||||||
color: #1068bf;
|
|
||||||
}
|
|
||||||
hr {
|
hr {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,6 +195,8 @@ module Members
|
||||||
end
|
end
|
||||||
|
|
||||||
def publish_event!
|
def publish_event!
|
||||||
|
return unless member_created_namespace_id
|
||||||
|
|
||||||
Gitlab::EventStore.publish(
|
Gitlab::EventStore.publish(
|
||||||
Members::MembersAddedEvent.new(data: {
|
Members::MembersAddedEvent.new(data: {
|
||||||
source_id: source.id,
|
source_id: source.id,
|
||||||
|
|
|
@ -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
|
## 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.
|
This bug only exists in the UI and does not block the removal of Primary sites using any other method.
|
||||||
|
|
||||||
|
|
|
@ -1123,7 +1123,7 @@ postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
|
||||||
|
|
||||||
### Reinitialize a replica
|
### 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
|
1. [Check the replication status](#check-replication-status) to confirm which server
|
||||||
needs to be reinitialized. For example:
|
needs to be reinitialized. For example:
|
||||||
|
|
|
@ -306,7 +306,7 @@ end
|
||||||
### Remove Sidekiq jobs for given parameters (destructive)
|
### Remove Sidekiq jobs for given parameters (destructive)
|
||||||
|
|
||||||
The general method to kill jobs conditionally is the following command, which
|
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
|
```ruby
|
||||||
queue = Sidekiq::Queue.new('<queue name>')
|
queue = Sidekiq::Queue.new('<queue name>')
|
||||||
|
|
|
@ -317,7 +317,7 @@ with its `partition_id`, and we will be able to find the partition that the
|
||||||
pipeline data is stored in.
|
pipeline data is stored in.
|
||||||
|
|
||||||
We will need to constrain access to searching through pipelines, builds,
|
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
|
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
|
through archived pipelines data. It will be necessary to have different access
|
||||||
patterns to access archived data in the UI and API.
|
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
|
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
|
```plaintext
|
||||||
ArgumentError: The association scope 'builds' is instance dependent (the
|
ArgumentError: The association scope 'builds' is instance dependent (the
|
||||||
|
|
|
@ -27,7 +27,7 @@ application.
|
||||||
Let's first consider entities with no inherent time-related bias for their data.
|
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
|
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.
|
record is accessed or updated.
|
||||||
|
|
||||||
On the other hand, a good example for datasets with extreme time-decay effects are logs and time
|
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
|
### Immutability
|
||||||
|
|
||||||
The third characteristic of time-decay data is that their **time-decay status does not change**.
|
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**
|
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
|
expensive (for example, by archiving or moving them to less expensive storage) without having to worry about
|
||||||
|
|
|
@ -198,7 +198,7 @@ To make a runner pick untagged jobs:
|
||||||
1. Select **Save changes** for the changes to take effect.
|
1. Select **Save changes** for the changes to take effect.
|
||||||
|
|
||||||
NOTE:
|
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.
|
Below are some example scenarios of different variations.
|
||||||
|
|
||||||
|
|
|
@ -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.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-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-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` | |
|
| (none, awaiting macOS 13) | `beta` | |
|
||||||
|
|
|
@ -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.
|
- 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.
|
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
|
- It all doesn't matter if the platform is not secure and we
|
||||||
are leaking credentials or secrets.
|
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.
|
- 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
|
### 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
|
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
|
a performance or reliability improvement, make sure that you measure things before
|
||||||
you optimize them.
|
you optimize them.
|
||||||
|
|
|
@ -44,7 +44,7 @@ into this category.
|
||||||
|
|
||||||
## Isolation
|
## 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
|
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.
|
can take a long time to run it's possible for new versions to be deployed while they are still running.
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ into this category.
|
||||||
|
|
||||||
## Isolation
|
## 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).
|
models defined in `app/models` except the `ApplicationRecord` classes).
|
||||||
Because these migrations can take a long time to run, it's possible
|
Because these migrations can take a long time to run, it's possible
|
||||||
for new versions to deploy while the migrations are still running.
|
for new versions to deploy while the migrations are still running.
|
||||||
|
|
|
@ -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.
|
that all epics should have a user-generated description.
|
||||||
|
|
||||||
After checking our production database, we know that there are `epics` with `NULL` descriptions,
|
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:
|
NOTE:
|
||||||
Even if we did not have any epic with a `NULL` description, another instance of GitLab could have
|
Even if we did not have any epic with a `NULL` description, another instance of GitLab could have
|
||||||
|
|
|
@ -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`
|
the `#text ... limit: 100` helper (see below) when creating a table, or by using the `add_text_limit`
|
||||||
when altering an existing table.
|
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)
|
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.
|
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.
|
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
|
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:
|
NOTE:
|
||||||
Even if we did not have any record with a title larger than the provided limit, another
|
Even if we did not have any record with a title larger than the provided limit, another
|
||||||
|
|
|
@ -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
|
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
|
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
|
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
|
### Cardinality and selectivity
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,6 @@ The main purpose is for support. Per the website:
|
||||||
> creator and maintainer. Get prioritized support for issues and requests.
|
> 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
|
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.
|
Details on the billing account and gem licensing can be found in the Engineering 1Password vault.
|
||||||
|
|
|
@ -111,7 +111,7 @@ The specified project export file in `archive_path` is missing.
|
||||||
|
|
||||||
##### `Exception: Permission denied @ rb_sysopen - (filename)`
|
##### `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
|
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.
|
public folder (for example `/tmp/`) fixes the issue.
|
||||||
|
|
|
@ -7,7 +7,7 @@ type: reference, api
|
||||||
|
|
||||||
# Internal API **(FREE)**
|
# 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
|
used by other consumers. This documentation is intended for people
|
||||||
working on the GitLab codebase.
|
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.
|
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
|
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
|
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.
|
not available to a wider community.
|
||||||
|
|
||||||
|
|
|
@ -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 close it from a commit or a merge request.
|
||||||
- You can't mark it as related to another issue.
|
- 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
|
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
|
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
|
define the interface for working with the new resource and update some other
|
||||||
|
|
|
@ -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
|
- private (`0`) - an entity is visible only to the approved members of the entity
|
||||||
|
|
||||||
By default, subgroups can **not** have higher visibility levels.
|
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
|
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
|
sub-projects have the same or lower visibility level. For example, a group can be set
|
||||||
|
|
|
@ -244,7 +244,7 @@ Example output:
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE:
|
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
|
## Settings that impact performance
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ This is just a sketch, but it shows the general idea: we would use whatever the
|
||||||
## End goal
|
## End goal
|
||||||
|
|
||||||
The guidelines in this document are meant to foster _better_ code reuse, by
|
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,
|
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
|
makes it easier to debug the code, and (hopefully) results in fewer performance
|
||||||
problems.
|
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.
|
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.
|
queries they produce.
|
||||||
|
|
||||||
Finders' `execute` method should return `ActiveRecord::Relation`. Exceptions
|
Finders' `execute` method should return `ActiveRecord::Relation`. Exceptions
|
||||||
|
|
|
@ -179,7 +179,7 @@ As the HyperLogLog algorithm is probabilistic, the **results always include erro
|
||||||
The highest encountered error rate is 4.9%.
|
The highest encountered error rate is 4.9%.
|
||||||
|
|
||||||
When correctly used, the `estimate_batch_distinct_count` method enables efficient counting over
|
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
|
##### estimate_batch_distinct_count method
|
||||||
|
|
||||||
|
|
|
@ -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
|
`HELM_UPGRADE_VALUES_FILE` [CI/CD variable](#cicd-variables) with
|
||||||
the path and name.
|
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.
|
[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:
|
NOTE:
|
||||||
|
|
|
@ -61,7 +61,7 @@ token as the API key.
|
||||||
|
|
||||||
## Running Spamcheck over TLS
|
## 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
|
However, Spamcheck can be deployed behind a reverse proxy which performs TLS
|
||||||
termination. In such a scenario, GitLab can be made to communicate with
|
termination. In such a scenario, GitLab can be made to communicate with
|
||||||
Spamcheck over TLS by specifying `tls://` scheme for the external Spamcheck URL
|
Spamcheck over TLS by specifying `tls://` scheme for the external Spamcheck URL
|
||||||
|
|
|
@ -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
|
- `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
|
- 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
|
- The `DAST_PATHS` variable has a limit of about 130kb. If you have a list or paths
|
||||||
greater than this, use `DAST_PATHS_FILE`.
|
greater than this, use `DAST_PATHS_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
|
then performs a build to fetch upstream dependency information. In the case of
|
||||||
containers, Dependency Scanning uses the compatible manifest and reports only these
|
containers, Dependency Scanning uses the compatible manifest and reports only these
|
||||||
declared software dependencies (and those installed as a sub-dependency).
|
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
|
into the container's base image. To identify pre-bundled dependencies, enable
|
||||||
[Container Scanning](../container_scanning/index.md) language scanning using the
|
[Container Scanning](../container_scanning/index.md) language scanning using the
|
||||||
[`CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` variable](../container_scanning/index.md#report-language-specific-findings).
|
[`CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` variable](../container_scanning/index.md#report-language-specific-findings).
|
||||||
|
|
|
@ -177,7 +177,7 @@ You can add an internal note **to an issue or an epic**. It's then visible only
|
||||||
Keep in mind:
|
Keep in mind:
|
||||||
|
|
||||||
- Replies to internal notes are also internal.
|
- 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:
|
Prerequisites:
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ if [ "$QA_SKIP_ALL_TESTS" == "true" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# set custom cache key to override default cache in pipeline-common because we use bundle to install gitlab-qa gem
|
# 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=$(cat <<YML
|
||||||
variables:
|
variables:
|
||||||
GITLAB_QA_CACHE_KEY: "$qa_cache_key"
|
GITLAB_QA_CACHE_KEY: "$qa_cache_key"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
import MockAdapter from 'axios-mock-adapter';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import * as urlUtility from '~/lib/utils/url_utility';
|
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 SidebarMediator from '~/sidebar/sidebar_mediator';
|
||||||
import SidebarStore from '~/sidebar/stores/sidebar_store';
|
import SidebarStore from '~/sidebar/stores/sidebar_store';
|
||||||
import Mock from './mock_data';
|
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];
|
const mockData = Mock.responseMap.GET[mediatorMockData.endpoint];
|
||||||
mock.onGet(mediatorMockData.endpoint).reply(200, mockData);
|
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());
|
const spy = jest.spyOn(mediator, 'processFetchedData').mockReturnValue(Promise.resolve());
|
||||||
|
await mediator.fetch();
|
||||||
|
|
||||||
return mediator.fetch().then(() => {
|
expect(spy).toHaveBeenCalledWith(mockData);
|
||||||
expect(spy).toHaveBeenCalledWith(mockData, mockGraphQlData);
|
spy.mockRestore();
|
||||||
|
|
||||||
spy.mockRestore();
|
|
||||||
graphQlSpy.mockRestore();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('processes fetched data', () => {
|
it('processes fetched data', () => {
|
||||||
|
|
|
@ -110,12 +110,61 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
|
||||||
expect(execute_service[:status]).to eq(:success)
|
expect(execute_service[:status]).to eq(:success)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
context 'when passing no user ids' do
|
context 'when passing no user ids' do
|
||||||
let(:user_id) { '' }
|
let(:user_id) { '' }
|
||||||
|
|
||||||
it 'does not add a member' do
|
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[:status]).to eq(:error)
|
||||||
expect(execute_service[:message]).to be_present
|
expect(execute_service[:message]).to be_present
|
||||||
expect(source.users).not_to include member
|
expect(source.users).not_to include member
|
||||||
|
|
Loading…
Reference in a new issue