Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
df2358a5f7
commit
e672c333df
39 changed files with 264 additions and 53 deletions
|
@ -24,6 +24,7 @@ import { responseMessageFromSuccess } from '../utils/response_message_parser';
|
|||
import { getInvalidFeedbackMessage } from '../utils/get_invalid_feedback_message';
|
||||
import ModalConfetti from './confetti.vue';
|
||||
import MembersTokenSelect from './members_token_select.vue';
|
||||
import UserLimitNotification from './user_limit_notification.vue';
|
||||
|
||||
export default {
|
||||
name: 'InviteMembersModal',
|
||||
|
@ -37,6 +38,7 @@ export default {
|
|||
InviteModalBase,
|
||||
MembersTokenSelect,
|
||||
ModalConfetti,
|
||||
UserLimitNotification,
|
||||
},
|
||||
inject: ['newProjectPath'],
|
||||
props: {
|
||||
|
@ -308,6 +310,11 @@ export default {
|
|||
<span v-if="isCelebration">{{ $options.labels.modal.celebrate.intro }} </span>
|
||||
<modal-confetti v-if="isCelebration" />
|
||||
</template>
|
||||
|
||||
<template #user-limit-notification>
|
||||
<user-limit-notification />
|
||||
</template>
|
||||
|
||||
<template #select="{ validationState, labelId }">
|
||||
<members-token-select
|
||||
v-model="newUsersToInvite"
|
||||
|
|
|
@ -215,6 +215,8 @@ export default {
|
|||
<slot name="intro-text-after"></slot>
|
||||
</div>
|
||||
|
||||
<slot name="user-limit-notification"></slot>
|
||||
|
||||
<gl-form-group
|
||||
:invalid-feedback="invalidFeedbackMessage"
|
||||
:state="validationState"
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
<script>
|
||||
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
|
||||
import { s__, n__, sprintf } from '~/locale';
|
||||
|
||||
const CLOSE_TO_LIMIT_COUNT = 2;
|
||||
|
||||
const WARNING_ALERT_TITLE = s__(
|
||||
'InviteMembersModal|You only have space for %{count} more %{members} in %{name}',
|
||||
);
|
||||
|
||||
const DANGER_ALERT_TITLE = s__(
|
||||
"InviteMembersModal|You've reached your %{count} %{members} limit for %{name}",
|
||||
);
|
||||
|
||||
const CLOSE_TO_LIMIT_MESSAGE = s__(
|
||||
'InviteMembersModal|To get more members an owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier.',
|
||||
);
|
||||
|
||||
const REACHED_LIMIT_MESSAGE = s__(
|
||||
'InviteMembersModal|New members will be unable to participate. You can manage your members by removing ones you no longer need.',
|
||||
).concat(' ', CLOSE_TO_LIMIT_MESSAGE);
|
||||
|
||||
export default {
|
||||
name: 'UserLimitNotification',
|
||||
components: { GlAlert, GlSprintf, GlLink },
|
||||
inject: ['name', 'newTrialRegistrationPath', 'purchasePath', 'freeUsersLimit', 'membersCount'],
|
||||
computed: {
|
||||
reachedLimit() {
|
||||
return this.isLimit();
|
||||
},
|
||||
closeToLimit() {
|
||||
return this.isLimit(CLOSE_TO_LIMIT_COUNT);
|
||||
},
|
||||
warningAlertTitle() {
|
||||
return sprintf(WARNING_ALERT_TITLE, {
|
||||
count: this.freeUsersLimit - this.membersCount,
|
||||
members: this.pluralMembers(this.freeUsersLimit - this.membersCount),
|
||||
name: this.name,
|
||||
});
|
||||
},
|
||||
dangerAlertTitle() {
|
||||
return sprintf(DANGER_ALERT_TITLE, {
|
||||
count: this.freeUsersLimit,
|
||||
members: this.pluralMembers(this.freeUsersLimit),
|
||||
name: this.name,
|
||||
});
|
||||
},
|
||||
variant() {
|
||||
return this.reachedLimit ? 'danger' : 'warning';
|
||||
},
|
||||
title() {
|
||||
return this.reachedLimit ? this.dangerAlertTitle : this.warningAlertTitle;
|
||||
},
|
||||
message() {
|
||||
if (this.reachedLimit) {
|
||||
return this.$options.i18n.reachedLimitMessage;
|
||||
}
|
||||
|
||||
return this.$options.i18n.closeToLimitMessage;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isLimit(deviation = 0) {
|
||||
if (this.freeUsersLimit && this.membersCount) {
|
||||
return this.membersCount >= this.freeUsersLimit - deviation;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
pluralMembers(count) {
|
||||
return n__('member', 'members', count);
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
reachedLimitMessage: REACHED_LIMIT_MESSAGE,
|
||||
closeToLimitMessage: CLOSE_TO_LIMIT_MESSAGE,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-alert
|
||||
v-if="reachedLimit || closeToLimit"
|
||||
:variant="variant"
|
||||
:dismissible="false"
|
||||
:title="title"
|
||||
>
|
||||
<gl-sprintf :message="message">
|
||||
<template #trialLink="{ content }">
|
||||
<gl-link :href="newTrialRegistrationPath" class="gl-label-link">{{ content }}</gl-link>
|
||||
</template>
|
||||
<template #upgradeLink="{ content }">
|
||||
<gl-link :href="purchasePath" class="gl-label-link">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</gl-alert>
|
||||
</template>
|
|
@ -24,7 +24,12 @@ export default (function initInviteMembersModal() {
|
|||
el,
|
||||
name: 'InviteMembersModalRoot',
|
||||
provide: {
|
||||
name: el.dataset.name,
|
||||
newProjectPath: el.dataset.newProjectPath,
|
||||
newTrialRegistrationPath: el.dataset.newTrialRegistrationPath,
|
||||
purchasePath: el.dataset.purchasePath,
|
||||
freeUsersLimit: el.dataset.freeUsersLimit && parseInt(el.dataset.freeUsersLimit, 10),
|
||||
membersCount: el.dataset.membersCount && parseInt(el.dataset.membersCount, 10),
|
||||
},
|
||||
render: (createElement) =>
|
||||
createElement(InviteMembersModal, {
|
||||
|
|
|
@ -47,6 +47,9 @@ export const typePolicies = {
|
|||
DesignCollection: {
|
||||
merge: true,
|
||||
},
|
||||
TreeEntry: {
|
||||
keyFields: ['webPath'],
|
||||
},
|
||||
};
|
||||
|
||||
export const stripWhitespaceFromQuery = (url, path) => {
|
||||
|
|
|
@ -33,6 +33,9 @@ export default {
|
|||
description() {
|
||||
return this.runner.description;
|
||||
},
|
||||
ipAddress() {
|
||||
return this.runner.ipAddress;
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
I18N_LOCKED_RUNNER_DESCRIPTION,
|
||||
|
@ -53,10 +56,11 @@ export default {
|
|||
:title="$options.i18n.I18N_LOCKED_RUNNER_DESCRIPTION"
|
||||
name="lock"
|
||||
/>
|
||||
<tooltip-on-truncate class="gl-display-block" :title="description" truncate-target="child">
|
||||
<div class="gl-text-truncate">
|
||||
{{ description }}
|
||||
</div>
|
||||
<tooltip-on-truncate class="gl-display-block gl-text-truncate" :title="description">
|
||||
{{ description }}
|
||||
</tooltip-on-truncate>
|
||||
<tooltip-on-truncate class="gl-display-block gl-text-truncate" :title="ipAddress">
|
||||
{{ __('IP Address') }} <strong>{{ ipAddress }}</strong>
|
||||
</tooltip-on-truncate>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -60,7 +60,6 @@ export default {
|
|||
tableField({ key: 'status', label: s__('Runners|Status') }),
|
||||
tableField({ key: 'summary', label: s__('Runners|Runner'), thClasses: ['gl-lg-w-25p'] }),
|
||||
tableField({ key: 'version', label: __('Version') }),
|
||||
tableField({ key: 'ipAddress', label: __('IP') }),
|
||||
tableField({ key: 'jobCount', label: __('Jobs') }),
|
||||
tableField({ key: 'tagList', label: __('Tags'), thClasses: ['gl-lg-w-25p'] }),
|
||||
tableField({ key: 'contactedAt', label: __('Last contact') }),
|
||||
|
@ -99,12 +98,6 @@ export default {
|
|||
</tooltip-on-truncate>
|
||||
</template>
|
||||
|
||||
<template #cell(ipAddress)="{ item: { ipAddress } }">
|
||||
<tooltip-on-truncate class="gl-display-block gl-text-truncate" :title="ipAddress">
|
||||
{{ ipAddress }}
|
||||
</tooltip-on-truncate>
|
||||
</template>
|
||||
|
||||
<template #cell(jobCount)="{ item: { jobCount } }">
|
||||
{{ formatJobCount(jobCount) }}
|
||||
</template>
|
||||
|
|
|
@ -79,7 +79,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
resolveConflictsFromCli: helpPagePath('ee/user/project/merge_requests/conflicts.html', {
|
||||
resolveConflictsFromCli: helpPagePath('user/project/merge_requests/conflicts', {
|
||||
anchor: 'resolve-conflicts-from-the-command-line',
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -46,6 +46,7 @@ module InviteMembersHelper
|
|||
}
|
||||
end
|
||||
|
||||
# Overridden in EE
|
||||
def common_invite_modal_dataset(source)
|
||||
dataset = {
|
||||
id: source.id,
|
||||
|
|
|
@ -4,7 +4,7 @@ class Gitlab::Seeder::Users
|
|||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
RANDOM_USERS_COUNT = 20
|
||||
MASS_NAMESPACES_COUNT = 100
|
||||
MASS_NAMESPACES_COUNT = ENV['CI'] ? 1 : 100
|
||||
MASS_USERS_COUNT = ENV['CI'] ? 10 : 1_000_000
|
||||
attr_reader :opts
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ class Gitlab::Seeder::ProjectFeatures
|
|||
Gitlab::Seeder.with_mass_insert(Project.count, "Project features") do
|
||||
Project.each_batch(of: BATCH_SIZE) do |batch, index|
|
||||
range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
|
||||
count = index * BATCH_SIZE
|
||||
count = index * batch.size
|
||||
|
||||
Gitlab::Seeder.log_message("Creating project features: #{count}.")
|
||||
ActiveRecord::Base.connection.execute <<~SQL
|
||||
|
|
|
@ -13,7 +13,7 @@ class Gitlab::Seeder::ProjectRoutes
|
|||
Gitlab::Seeder.with_mass_insert(Project.count, "Project routes") do
|
||||
Project.each_batch(of: BATCH_SIZE / 2) do |batch, index|
|
||||
range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
|
||||
count = index * BATCH_SIZE / 2
|
||||
count = index * batch.size
|
||||
|
||||
Gitlab::Seeder.log_message("Creating project routes: #{count}.")
|
||||
ActiveRecord::Base.connection.execute <<~SQL
|
||||
|
|
|
@ -32,7 +32,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
|
|||
|
||||
- [Install](../install/index.md): Requirements, directory structures, and installation methods.
|
||||
- [Reference architectures](reference_architectures/index.md): Add additional resources to support more users.
|
||||
- [Installing GitLab on Amazon Web Services (AWS)](../install/aws/index.md): Set up GitLab on Amazon AWS.
|
||||
- [Installing GitLab on Amazon Web Services (AWS)](../install/aws/index.md): Set up GitLab on Amazon AWS.
|
||||
- [Geo](geo/index.md): Replicate your GitLab instance to other geographic locations as a read-only fully operational version.
|
||||
- [Disaster Recovery](geo/disaster_recovery/index.md): Quickly fail-over to a different site with minimal effort in a disaster situation.
|
||||
- [Add License](../user/admin_area/license.md): Add a license at install time to unlock features that are in paid tiers of GitLab.
|
||||
|
|
|
@ -32,7 +32,7 @@ By default, macOS limits the <kbd>tab</kbd> key to **Text boxes and lists only**
|
|||
1. Open the **Shortcuts** tab.
|
||||
1. Enable the setting **Use keyboard navigation to move focus between controls**.
|
||||
|
||||
You can read more about enabling browser-specific keyboard navigation on [a11yproject](https://www.a11yproject.com/posts/2017-12-29-macos-browser-keyboard-navigation/).
|
||||
You can read more about enabling browser-specific keyboard navigation on [a11yproject](https://www.a11yproject.com/posts/macos-browser-keyboard-navigation/).
|
||||
|
||||
## Quick checklist
|
||||
|
||||
|
|
|
@ -457,6 +457,6 @@ General tips:
|
|||
## Additional Resources
|
||||
|
||||
- [WebPage Test](https://www.webpagetest.org) for testing site loading time and size.
|
||||
- [Google PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/) grades web pages and provides feedback to improve the page.
|
||||
- [Google PageSpeed Insights](https://pagespeed.web.dev/) grades web pages and provides feedback to improve the page.
|
||||
- [Profiling with Chrome DevTools](https://developer.chrome.com/docs/devtools/)
|
||||
- [Browser Diet](https://browserdiet.com/) is a community-built guide that catalogues practical tips for improving web page performance.
|
||||
|
|
|
@ -35,7 +35,7 @@ Vue component, but the integration of Source Editor is generally straightforward
|
|||
const editor = new SourceEditor({
|
||||
// Editor Options.
|
||||
// The list of all accepted options can be found at
|
||||
// https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html
|
||||
// https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.EditorOption.html
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -56,19 +56,19 @@ An instance of Source Editor accepts the following configuration options:
|
|||
| `blobContent` | `false` | `String`: The initial content to render in the editor. |
|
||||
| `extensions` | `false` | `Array`: Extensions to use in this instance. |
|
||||
| `blobGlobalId` | `false` | `String`: An auto-generated property.<br>**Note:** This property may go away in the future. Do not pass `blobGlobalId` unless you know what you're doing.|
|
||||
| Editor Options | `false` | `Object(s)`: Any property outside of the list above is treated as an Editor Option for this particular instance. Use this field to override global Editor Options on the instance level. A full [index of Editor Options](https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html) is available. |
|
||||
| Editor Options | `false` | `Object(s)`: Any property outside of the list above is treated as an Editor Option for this particular instance. Use this field to override global Editor Options on the instance level. A full [index of Editor Options](https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.EditorOption.html) is available. |
|
||||
|
||||
## API
|
||||
|
||||
The editor uses the same public API as
|
||||
[provided by Monaco editor](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html)
|
||||
[provided by Monaco editor](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneCodeEditor.html)
|
||||
with additional functions on the instance level:
|
||||
|
||||
| Function | Arguments | Description
|
||||
| --------------------- | ----- | ----- |
|
||||
| `updateModelLanguage` | `path`: String | Updates the instance's syntax highlighting to follow the extension of the passed `path`. Available only on the instance level.|
|
||||
| `use` | Array of objects | Array of extensions to apply to the instance. Accepts only the array of _objects_. You must fetch the extensions' ES6 modules must be fetched and resolved in your views or components before they are passed to `use`. This property is available on _instance_ (applies extension to this particular instance) and _global editor_ (applies the same extension to all instances) levels. |
|
||||
| Monaco Editor options | See [documentation](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) | Default Monaco editor options |
|
||||
| Monaco Editor options | See [documentation](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneCodeEditor.html) | Default Monaco editor options |
|
||||
|
||||
## Tips
|
||||
|
||||
|
@ -202,7 +202,7 @@ export default {
|
|||
|
||||
In the code example, `this` refers to the instance. By referring to the instance,
|
||||
we can access the complete underlying
|
||||
[Monaco editor API](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html),
|
||||
[Monaco editor API](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneCodeEditor.html),
|
||||
which includes functions like `getValue()`.
|
||||
|
||||
Now let's use our extension:
|
||||
|
|
|
@ -499,7 +499,7 @@ component under test, with the `computed` property, for example). Remember to us
|
|||
We should test for events emitted in response to an action in our component. This is used to
|
||||
verify the correct events are being fired with the correct arguments.
|
||||
|
||||
For any DOM events we should use [`trigger`](https://vue-test-utils.vuejs.org/api/wrapper/#trigger)
|
||||
For any DOM events we should use [`trigger`](https://v1.test-utils.vuejs.org/api/wrapper/#trigger)
|
||||
to fire out event.
|
||||
|
||||
```javascript
|
||||
|
@ -530,7 +530,7 @@ it('should fire the itemClicked event', () => {
|
|||
```
|
||||
|
||||
We should verify an event has been fired by asserting against the result of the
|
||||
[`emitted()`](https://vue-test-utils.vuejs.org/api/wrapper/#emitted) method.
|
||||
[`emitted()`](https://v1.test-utils.vuejs.org/api/wrapper/#emitted) method.
|
||||
|
||||
## Vue.js Expert Role
|
||||
|
||||
|
|
|
@ -156,6 +156,6 @@ export default {
|
|||
</template>
|
||||
```
|
||||
|
||||
[In Vue 3](https://v3.vuejs.org/guide/migration/props-default-this.html#props-default-function-this-access),
|
||||
[In Vue 3](https://v3-migration.vuejs.org/breaking-changes/props-default-this.html),
|
||||
the props default value factory is passed the raw props as an argument, and can
|
||||
also access injections.
|
||||
|
|
|
@ -203,7 +203,7 @@ Go's [`regexp`](https://pkg.go.dev/regexp) package uses `re2` and isn't vulnerab
|
|||
|
||||
### Description
|
||||
|
||||
A [Server-side Request Forgery (SSRF)](https://www.hackerone.com/blog-How-To-Server-Side-Request-Forgery-SSRF) is an attack in which an attacker
|
||||
A [Server-side Request Forgery (SSRF)](https://www.hackerone.com/application-security/how-server-side-request-forgery-ssrf) is an attack in which an attacker
|
||||
is able coerce a application into making an outbound request to an unintended
|
||||
resource. This resource is usually internal. In GitLab, the connection most
|
||||
commonly uses HTTP, but an SSRF can be performed with any protocol, such as
|
||||
|
|
|
@ -21,7 +21,7 @@ a level that is difficult to manage.
|
|||
Test heuristics can help solve this problem. They concisely address many of the common ways bugs
|
||||
manifest themselves in our code. When designing our tests, take time to review known test heuristics to inform
|
||||
our test design. We can find some helpful heuristics documented in the Handbook in the
|
||||
[Test Engineering](https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-heuristics) section.
|
||||
[Test Engineering](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/test-engineering/#test-heuristics) section.
|
||||
|
||||
## RSpec
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Execution context selection
|
||||
|
||||
Some tests are designed to be run against specific environments, or in specific [pipelines](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#scheduled-qa-test-pipelines) or jobs. We can specify the test execution context using the `only` and `except` metadata.
|
||||
Some tests are designed to be run against specific environments, or in specific [pipelines](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/debugging-qa-test-failures/#scheduled-qa-test-pipelines) or jobs. We can specify the test execution context using the `only` and `except` metadata.
|
||||
|
||||
## Available switches
|
||||
|
||||
|
@ -118,7 +118,7 @@ To run a test tagged with `except` locally, you can either:
|
|||
|
||||
Similarly to specifying that a test should only run against a specific environment, it's also possible to quarantine a
|
||||
test only when it runs against a specific environment. The syntax is exactly the same, except that the `only: { ... }`
|
||||
hash is nested in the [`quarantine: { ... }`](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests) hash.
|
||||
hash is nested in the [`quarantine: { ... }`](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/debugging-qa-test-failures/#quarantining-tests) hash.
|
||||
For example, `quarantine: { only: { subdomain: :staging } }` only quarantines the test when run against `staging`.
|
||||
|
||||
The quarantine feature can be explicitly disabled with the `DISABLE_QUARANTINE` environment variable. This can be useful when running tests locally.
|
||||
|
|
|
@ -162,7 +162,7 @@ for details.
|
|||
|
||||
## Confirming that end-to-end tests pass with a feature flag enabled
|
||||
|
||||
End-to-end tests should pass with a feature flag enabled before it is enabled on Staging or on GitLab.com. Tests that need to be updated should be identified as part of [quad-planning](https://about.gitlab.com/handbook/engineering/quality/quad-planning/). The relevant [counterpart Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) is responsible for updating the tests or assisting another engineer to do so. However, if a change does not go through quad-planning and a required test update is not made, test failures could block deployment.
|
||||
End-to-end tests should pass with a feature flag enabled before it is enabled on Staging or on GitLab.com. Tests that need to be updated should be identified as part of [quad-planning](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/quad-planning/). The relevant [counterpart Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) is responsible for updating the tests or assisting another engineer to do so. However, if a change does not go through quad-planning and a required test update is not made, test failures could block deployment.
|
||||
|
||||
### Automatic test execution when a feature flag definition changes
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ The [existing scenarios](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/doc
|
|||
that run in the downstream `gitlab-qa-mirror` pipeline include many tests, but there are times when you might want to run a
|
||||
test or a group of tests that are different than the groups in any of the existing scenarios.
|
||||
|
||||
For example, when we [dequarantine](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#dequarantining-tests)
|
||||
For example, when we [dequarantine](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/debugging-qa-test-failures/#dequarantining-tests)
|
||||
a flaky test we first want to make sure that it's no longer flaky.
|
||||
We can do that using the `ce:custom-parallel` and `ee:custom-parallel` jobs.
|
||||
Both are manual jobs that you can configure using custom variables.
|
||||
|
|
|
@ -33,7 +33,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
|
|||
| `:only` | The test is only to be run in specific execution contexts. See [test execution context selection](execution_context_selection.md) for more information. |
|
||||
| `:orchestrated` | The GitLab instance under test may be [configured by `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#orchestrated-tests) to be different to the default GitLab configuration, or `gitlab-qa` may launch additional services in separate Docker containers, or both. Tests tagged with `:orchestrated` are excluded when testing environments where we can't dynamically modify the GitLab configuration (for example, Staging). |
|
||||
| `:packages` | The test requires a GitLab instance that has the [Package Registry](../../../administration/packages/#gitlab-package-registry-administration) enabled. |
|
||||
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), runs in a separate job that only includes quarantined tests, and is allowed to fail. The test is skipped in its regular job so that if it fails it doesn't hold up the pipeline. Note that you can also [quarantine a test only when it runs in a specific context](execution_context_selection.md#quarantine-a-test-for-a-specific-environment). |
|
||||
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/debugging-qa-test-failures/#quarantining-tests), runs in a separate job that only includes quarantined tests, and is allowed to fail. The test is skipped in its regular job so that if it fails it doesn't hold up the pipeline. Note that you can also [quarantine a test only when it runs in a specific context](execution_context_selection.md#quarantine-a-test-for-a-specific-environment). |
|
||||
| `:relative_url` | The test requires a GitLab instance to be installed under a [relative URL](../../../install/relative_url.md). |
|
||||
| `:reliable` | The test has been [promoted to a reliable test](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/reliable-tests/#promoting-an-existing-test-to-reliable) meaning it passes consistently in all pipelines, including merge requests. |
|
||||
| `:repository_storage` | The test requires a GitLab instance to be configured to use multiple [repository storage paths](../../../administration/repository_storage_paths.md). Paired with the `:orchestrated` tag. |
|
||||
|
|
|
@ -299,7 +299,7 @@ Geo requires an EE license. To visit the Geo sites in your browser, you need a r
|
|||
|
||||
#### Notes
|
||||
|
||||
- You can find the full image address from a pipeline by [following these instructions](https://about.gitlab.com/handbook/engineering/quality/guidelines/tips-and-tricks/#running-gitlab-qa-pipeline-against-a-specific-gitlab-release). You might be prompted to set the `GITLAB_QA_ACCESS_TOKEN` variable if you specify the full image address.
|
||||
- You can find the full image address from a pipeline by [following these instructions](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/tips-and-tricks/#running-gitlab-qa-pipeline-against-a-specific-gitlab-release). You might be prompted to set the `GITLAB_QA_ACCESS_TOKEN` variable if you specify the full image address.
|
||||
- You can increase the wait time for replication by setting `GEO_MAX_FILE_REPLICATION_TIME` and `GEO_MAX_DB_REPLICATION_TIME`. The default is 120 seconds.
|
||||
- To save time during tests, create a Personal Access Token with API access on the Geo primary node, and pass that value in as `GITLAB_QA_ACCESS_TOKEN` and `GITLAB_QA_ADMIN_ACCESS_TOKEN`.
|
||||
|
||||
|
@ -395,7 +395,7 @@ Tests that are tagged with `:mobile` can be run against specified mobile devices
|
|||
|
||||
Running directly against an environment like staging is not recommended because Sauce Labs test logs expose credentials. Therefore, it is best practice and the default to use a tunnel.
|
||||
|
||||
For tunnel installation instructions, read [Sauce Connect Proxy Installation](https://docs.saucelabs.com/secure-connections/sauce-connect/installation). To start the tunnel, after following the installation above, copy the run command in Sauce Labs > Tunnels (must be logged in to Sauce Labs with the credentials found in 1Password) and run in terminal.
|
||||
For tunnel installation instructions, read [Sauce Connect Proxy Installation](https://docs.saucelabs.com/secure-connections/sauce-connect/installation/index.html). To start the tunnel, after following the installation above, copy the run command in Sauce Labs > Tunnels (must be logged in to Sauce Labs with the credentials found in 1Password) and run in terminal.
|
||||
|
||||
NOTE:
|
||||
It is highly recommended to use `GITLAB_QA_ACCESS_TOKEN` to speed up tests and reduce flakiness.
|
||||
|
|
|
@ -28,7 +28,7 @@ To use the GitLab Gitpod integration, it must be enabled for your GitLab instanc
|
|||
1. It's [enabled and configured by a GitLab administrator](#configure-a-self-managed-instance).
|
||||
1. It's [enabled in their user settings](#enable-gitpod-in-your-user-settings).
|
||||
|
||||
To learn more about Gitpod, see their [features](https://www.gitpod.io/features) and
|
||||
To learn more about Gitpod, see their [features](https://www.gitpod.io/) and
|
||||
[documentation](https://www.gitpod.io/docs/).
|
||||
|
||||
## Enable Gitpod in your user settings
|
||||
|
|
|
@ -89,7 +89,7 @@ at Super User also has relevant information.
|
|||
|
||||
**Omnibus Trusted Chain**
|
||||
|
||||
[Install the self signed certificate or custom certificate authorities](https://docs.gitlab.com/omnibus/common_installation_problems/index.html#using-self-signed-certificate-or-custom-certificate-authorities)
|
||||
[Install the self signed certificate or custom certificate authorities](https://docs.gitlab.com/omnibus/troubleshooting.html#using-self-signed-certificate-or-custom-certificate-authorities)
|
||||
in to Omnibus GitLab.
|
||||
|
||||
It is enough to concatenate the certificate to the main trusted certificate
|
||||
|
|
|
@ -56,7 +56,7 @@ or the Jira DVCS (distributed version control system) connector,
|
|||
## Authentication in Jira
|
||||
|
||||
The authentication method in Jira depends on whether you host Jira on your own server or on
|
||||
[Atlassian cloud](https://www.atlassian.com/cloud):
|
||||
[Atlassian cloud](https://www.atlassian.com/migration/assess/why-cloud):
|
||||
|
||||
- **Jira Server** supports basic authentication. When connecting, a **username and password** are
|
||||
required. Connecting to Jira Server using the Central Authentication Service (CAS) is not possible. For more information, read
|
||||
|
|
|
@ -477,7 +477,7 @@ Mattermost System Console or manually.
|
|||
If a configuration setting is specified via both the `gitlab.rb` (as an environment variable)
|
||||
and `config.json` files, the environment variable gets precedence.
|
||||
|
||||
If you encounter any issues [visit the GitLab Mattermost troubleshooting forum](https://forum.mattermost.org/t/upgrading-to-gitlab-mattermost-in-gitlab-8-9/1735) and share any relevant portions of `mattermost.log` along with the step at which you encountered issues.
|
||||
If you encounter any issues [visit the GitLab Mattermost troubleshooting forum](https://forum.mattermost.com/t/upgrading-to-gitlab-mattermost-in-gitlab-8-9/1735) and share any relevant portions of `mattermost.log` along with the step at which you encountered issues.
|
||||
|
||||
### Upgrading GitLab Mattermost outside of GitLab
|
||||
|
||||
|
@ -523,7 +523,7 @@ You can fix this by setting up a `mattermost-cli` [shell alias](#mattermost-comm
|
|||
|
||||
For help and support around your GitLab Mattermost deployment please see:
|
||||
|
||||
- [Troubleshooting Forum](https://forum.mattermost.org/t/how-to-use-the-troubleshooting-forum/150) for configuration questions and issues.
|
||||
- [Troubleshooting Forum](https://forum.mattermost.com/t/how-to-use-the-troubleshooting-forum/150) for configuration questions and issues.
|
||||
- [Troubleshooting FAQ](https://docs.mattermost.com/install/troubleshooting.html).
|
||||
- [Mattermost GitLab Issues Support Handbook](https://docs.mattermost.com/process/support.html?highlight=omnibus#gitlab-issues).
|
||||
- [GitLab Mattermost issue tracker](https://gitlab.com/gitlab-org/gitlab-mattermost/-/issues) for verified bugs with repro steps.
|
||||
|
|
|
@ -11,7 +11,7 @@ You can integrate your GitLab instance with [Salesforce](https://www.salesforce.
|
|||
## Create a Salesforce Connected App
|
||||
|
||||
To enable Salesforce OmniAuth provider, you must use Salesforce's credentials for your GitLab instance.
|
||||
To get the credentials (a pair of Client ID and Client Secret), you must [create a Connected App](https://help.salesforce.com/s/articleView?id=connected_app_create.htm&type=5) on Salesforce.
|
||||
To get the credentials (a pair of Client ID and Client Secret), you must [create a Connected App](https://help.salesforce.com/s/articleView?id=sf.connected_app_create.htm&type=5) on Salesforce.
|
||||
|
||||
1. Sign in to [Salesforce](https://login.salesforce.com/).
|
||||
|
||||
|
|
|
@ -790,7 +790,7 @@ documentation on how to use SAML to sign in to GitLab.
|
|||
Examples:
|
||||
|
||||
- [ADFS (Active Directory Federation Services)](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
|
||||
- [Auth0](https://auth0.com/docs/configure/saml-configuration/configure-auth0-saml-identity-provider)
|
||||
- [Auth0](https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/configure-auth0-saml-identity-provider)
|
||||
- [PingOne by Ping Identity](http://docs.pingidentity.com/bundle/pingoneforenterprise/page/xsh1564020480660-1.html)
|
||||
|
||||
GitLab provides the following setup notes for guidance only.
|
||||
|
|
|
@ -34,8 +34,8 @@ GitLab SaaS or GitLab self-managed:
|
|||
your own GitLab instance.
|
||||
|
||||
On a GitLab self-managed instance, a GitLab subscription provides the same set of
|
||||
features for _all_ users. On GitLab SaaS, you can apply a subscription to either
|
||||
a group or a personal namespace.
|
||||
features for _all_ users. On GitLab SaaS, you can apply a subscription to a group
|
||||
namespace. You cannot apply a subscription to a personal namespace.
|
||||
|
||||
NOTE:
|
||||
Subscriptions cannot be transferred between GitLab SaaS and GitLab self-managed.
|
||||
|
|
|
@ -576,6 +576,8 @@ for how to proceed.
|
|||
- The support of PostgreSQL 11 [has been dropped](../install/requirements.md#database). Make sure to [update your database](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server) to version 12 before updating to GitLab 14.0.
|
||||
|
||||
- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
|
||||
- See [Custom Rack Attack initializers](#custom-rack-attack-initializers) if you persist your own custom Rack Attack
|
||||
initializers during upgrades.
|
||||
|
||||
#### Upgrading to later 14.Y releases
|
||||
|
||||
|
@ -754,6 +756,14 @@ all servers must first be upgraded to 13.1.Z before upgrading to 13.2.0 or later
|
|||
|
||||
1. Only then, continue to upgrade to later versions of GitLab.
|
||||
|
||||
#### Custom Rack Attack initializers
|
||||
|
||||
From GitLab 13.0.1, custom Rack Attack initializers (`config/initializers/rack_attack.rb`) are replaced with initializers
|
||||
supplied with GitLab during upgrades. We recommend you use these GitLab-supplied initializers.
|
||||
|
||||
If you persist your own Rack Attack initializers between upgrades, you might
|
||||
[get `500` errors](https://gitlab.com/gitlab-org/gitlab/-/issues/334681) when [upgrading to GitLab 14.0 and later](#1400).
|
||||
|
||||
### 12.2.0
|
||||
|
||||
In 12.2.0, we enabled Rails' authenticated cookie encryption. Old sessions are
|
||||
|
|
|
@ -79,7 +79,7 @@ the Container Registry after the policy runs. The next time the policy runs, the
|
|||
so it may take multiple runs for all tags to be deleted.
|
||||
|
||||
WARNING:
|
||||
GitLab self-managed installs support for third-party container registries that comply with the
|
||||
GitLab self-managed installations support third-party container registries that comply with the
|
||||
[Docker Registry HTTP API V2](https://docs.docker.com/registry/spec/api/)
|
||||
specification. However, this specification does not include a tag delete operation. Therefore, when
|
||||
interacting with third-party container registries, GitLab uses a workaround to delete tags. See the
|
||||
|
|
|
@ -18659,9 +18659,6 @@ msgstr ""
|
|||
msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
|
||||
msgstr ""
|
||||
|
||||
msgid "IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP Address"
|
||||
msgstr ""
|
||||
|
||||
|
@ -20542,6 +20539,9 @@ msgstr ""
|
|||
msgid "InviteMembersModal|Members were successfully added"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|New members will be unable to participate. You can manage your members by removing ones you no longer need."
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|Search for a group to invite"
|
||||
msgstr ""
|
||||
|
||||
|
@ -20560,6 +20560,12 @@ msgstr ""
|
|||
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|To get more members an owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
|
||||
msgstr ""
|
||||
|
||||
|
@ -20572,6 +20578,9 @@ msgstr ""
|
|||
msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|You've reached your %{count} %{members} limit for %{name}"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembers|Invite a group"
|
||||
msgstr ""
|
||||
|
||||
|
@ -44459,6 +44468,11 @@ msgstr ""
|
|||
msgid "math|There was an error rendering this math block"
|
||||
msgstr ""
|
||||
|
||||
msgid "member"
|
||||
msgid_plural "members"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "merge request"
|
||||
msgid_plural "merge requests"
|
||||
msgstr[0] ""
|
||||
|
|
|
@ -213,7 +213,7 @@ function create_application_secret() {
|
|||
local initial_root_password_shared_secret
|
||||
local gitlab_license_shared_secret
|
||||
|
||||
initial_root_password_shared_secret=$(kubectl get secret --namespace ${namespace} --no-headers -o=custom-columns=NAME:.metadata.name shared-gitlab-initial-root-password | tail -n 1)
|
||||
initial_root_password_shared_secret=$(kubectl get secret --namespace ${namespace} --no-headers -o=custom-columns=NAME:.metadata.name shared-gitlab-initial-root-password 2> /dev/null | tail -n 1)
|
||||
if [[ "${initial_root_password_shared_secret}" == "" ]]; then
|
||||
echoinfo "Creating the 'shared-gitlab-initial-root-password' secret in the ${namespace} namespace..." true
|
||||
kubectl create secret generic --namespace "${namespace}" \
|
||||
|
@ -226,7 +226,7 @@ function create_application_secret() {
|
|||
|
||||
if [ -z "${REVIEW_APPS_EE_LICENSE_FILE}" ]; then echo "License not found" && return; fi
|
||||
|
||||
gitlab_license_shared_secret=$(kubectl get secret --namespace ${namespace} --no-headers -o=custom-columns=NAME:.metadata.name shared-gitlab-license | tail -n 1)
|
||||
gitlab_license_shared_secret=$(kubectl get secret --namespace ${namespace} --no-headers -o=custom-columns=NAME:.metadata.name shared-gitlab-license 2> /dev/null | tail -n 1)
|
||||
if [[ "${gitlab_license_shared_secret}" == "" ]]; then
|
||||
echoinfo "Creating the 'shared-gitlab-license' secret in the ${namespace} namespace..." true
|
||||
kubectl create secret generic --namespace "${namespace}" \
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import { GlAlert, GlSprintf } from '@gitlab/ui';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import UserLimitNotification from '~/invite_members/components/user_limit_notification.vue';
|
||||
|
||||
describe('UserLimitNotification', () => {
|
||||
let wrapper;
|
||||
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
|
||||
const createComponent = (providers = {}) => {
|
||||
wrapper = shallowMountExtended(UserLimitNotification, {
|
||||
provide: {
|
||||
name: 'my group',
|
||||
newTrialRegistrationPath: 'newTrialRegistrationPath',
|
||||
purchasePath: 'purchasePath',
|
||||
freeUsersLimit: 5,
|
||||
membersCount: 1,
|
||||
...providers,
|
||||
},
|
||||
stubs: { GlSprintf },
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('when limit is not reached', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('renders empty block', () => {
|
||||
expect(findAlert().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when close to limit', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ membersCount: 3 });
|
||||
});
|
||||
|
||||
it("renders user's limit notification", () => {
|
||||
const alert = findAlert();
|
||||
|
||||
expect(alert.attributes('title')).toEqual(
|
||||
'You only have space for 2 more members in my group',
|
||||
);
|
||||
|
||||
expect(alert.text()).toEqual(
|
||||
'To get more members an owner of this namespace can start a trial or upgrade to a paid tier.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when limit is reached', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ membersCount: 5 });
|
||||
});
|
||||
|
||||
it("renders user's limit notification", () => {
|
||||
const alert = findAlert();
|
||||
|
||||
expect(alert.attributes('title')).toEqual("You've reached your 5 members limit for my group");
|
||||
|
||||
expect(alert.text()).toEqual(
|
||||
'New members will be unable to participate. You can manage your members by removing ones you no longer need. To get more members an owner of this namespace can start a trial or upgrade to a paid tier.',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -5,6 +5,7 @@ import { INSTANCE_TYPE, PROJECT_TYPE } from '~/runner/constants';
|
|||
const mockId = '1';
|
||||
const mockShortSha = '2P6oDVDm';
|
||||
const mockDescription = 'runner-1';
|
||||
const mockIpAddress = '0.0.0.0';
|
||||
|
||||
describe('RunnerTypeCell', () => {
|
||||
let wrapper;
|
||||
|
@ -18,6 +19,7 @@ describe('RunnerTypeCell', () => {
|
|||
id: `gid://gitlab/Ci::Runner/${mockId}`,
|
||||
shortSha: mockShortSha,
|
||||
description: mockDescription,
|
||||
ipAddress: mockIpAddress,
|
||||
runnerType: INSTANCE_TYPE,
|
||||
...runner,
|
||||
},
|
||||
|
@ -59,6 +61,10 @@ describe('RunnerTypeCell', () => {
|
|||
expect(wrapper.text()).toContain(mockDescription);
|
||||
});
|
||||
|
||||
it('Displays the runner ip address', () => {
|
||||
expect(wrapper.text()).toContain(mockIpAddress);
|
||||
});
|
||||
|
||||
it('Displays a custom slot', () => {
|
||||
const slotContent = 'My custom runner summary';
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ describe('RunnerList', () => {
|
|||
'Status',
|
||||
'Runner',
|
||||
'Version',
|
||||
'IP',
|
||||
'Jobs',
|
||||
'Tags',
|
||||
'Last contact',
|
||||
|
@ -68,7 +67,7 @@ describe('RunnerList', () => {
|
|||
});
|
||||
|
||||
it('Displays details of a runner', () => {
|
||||
const { id, description, version, ipAddress, shortSha } = mockRunners[0];
|
||||
const { id, description, version, shortSha } = mockRunners[0];
|
||||
|
||||
// Badges
|
||||
expect(findCell({ fieldKey: 'status' }).text()).toMatchInterpolatedText(
|
||||
|
@ -83,7 +82,6 @@ describe('RunnerList', () => {
|
|||
|
||||
// Other fields
|
||||
expect(findCell({ fieldKey: 'version' }).text()).toBe(version);
|
||||
expect(findCell({ fieldKey: 'ipAddress' }).text()).toBe(ipAddress);
|
||||
expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('0');
|
||||
expect(findCell({ fieldKey: 'tagList' }).text()).toBe('');
|
||||
expect(findCell({ fieldKey: 'contactedAt' }).text()).toEqual(expect.any(String));
|
||||
|
|
Loading…
Reference in a new issue