Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-10-02 06:08:27 +00:00
parent 895563036a
commit 91ef4dcc05
50 changed files with 268 additions and 525 deletions

View file

@ -1,6 +1,6 @@
<script>
import { GlAlert } from '@gitlab/ui';
import { __ } from '~/locale';
import { __, sprintf } from '~/locale';
import ServiceDeskSetting from './service_desk_setting.vue';
import ServiceDeskService from '../services/service_desk_service';
import eventHub from '../event_hub';
@ -122,11 +122,13 @@ export default {
this.incomingEmail = data?.service_desk_address;
this.showAlert(__('Changes were successfully made.'), 'success');
})
.catch(() =>
.catch(err => {
this.showAlert(
__('An error occurred while saving the template. Please check if the template exists.'),
),
)
sprintf(__('An error occured while making the changes: %{error}'), {
error: err?.response?.data?.message,
}),
);
})
.finally(() => {
this.isTemplateSaving = false;
});

View file

@ -1,5 +1,5 @@
<script>
import { GlButton, GlFormSelect, GlToggle, GlLoadingIcon } from '@gitlab/ui';
import { GlButton, GlFormSelect, GlToggle, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@ -17,6 +17,7 @@ export default {
GlFormSelect,
GlToggle,
GlLoadingIcon,
GlSprintf,
},
mixins: [glFeatureFlagsMixin()],
props: {
@ -60,6 +61,7 @@ export default {
selectedTemplate: this.initialSelectedTemplate,
outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
projectKey: this.initialProjectKey,
baseEmail: this.incomingEmail.replace(this.initialProjectKey, ''),
};
},
computed: {
@ -123,12 +125,33 @@ export default {
/>
</div>
</div>
<span v-if="projectKey" class="form-text text-muted">
<gl-sprintf :message="__('Emails sent to %{email} will still be supported')">
<template #email>
<code>{{ baseEmail }}</code>
</template>
</gl-sprintf>
</span>
</template>
<template v-else>
<gl-loading-icon :inline="true" />
<span class="sr-only">{{ __('Fetching incoming email') }}</span>
</template>
<template v-if="hasProjectKeySupport">
<label for="service-desk-project-suffix" class="mt-3">
{{ __('Project name suffix') }}
</label>
<input id="service-desk-project-suffix" v-model.trim="projectKey" class="form-control" />
<span class="form-text text-muted">
{{
__(
'Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address.',
)
}}
</span>
</template>
<label for="service-desk-template-select" class="mt-3">
{{ __('Template to append to all Service Desk issues') }}
</label>
@ -144,27 +167,16 @@ export default {
<span class="form-text text-muted">
{{ __('Emails sent from Service Desk will have this name') }}
</span>
<template v-if="hasProjectKeySupport">
<label for="service-desk-project-suffix" class="mt-3">
{{ __('Project name suffix') }}
</label>
<input id="service-desk-project-suffix" v-model.trim="projectKey" class="form-control" />
<span class="form-text text-muted mb-3">
{{
__(
'Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address.',
)
}}
</span>
</template>
<gl-button
variant="success"
class="gl-mt-5"
:disabled="isTemplateSaving"
@click="onSaveTemplate"
>
{{ __('Save changes') }}
</gl-button>
<div class="gl-display-flex gl-justify-content-end">
<gl-button
variant="success"
class="gl-mt-5"
:disabled="isTemplateSaving"
@click="onSaveTemplate"
>
{{ __('Save changes') }}
</gl-button>
</div>
</div>
</div>
</div>

View file

@ -90,6 +90,7 @@ export default {
:size="12"
:title="stateTitle"
:aria-label="state"
data-testid="referenceIcon"
/>
{{ displayReference }}
</component>
@ -105,6 +106,7 @@ export default {
:title="removeButtonLabel"
:aria-label="removeButtonLabel"
:disabled="removeDisabled"
data-testid="removeBtn"
type="button"
class="js-issue-token-remove-button"
@click="onRemoveRequest"

View file

@ -111,7 +111,7 @@ const mixins = {
return this.isMergeRequest && this.pipelineStatus && Object.keys(this.pipelineStatus).length;
},
isOpen() {
return this.state === 'opened';
return this.state === 'opened' || this.state === 'reopened';
},
isClosed() {
return this.state === 'closed';

View file

@ -22,8 +22,8 @@ module Postgresql
def self.lag_too_great?(max = 100.megabytes)
return false unless in_use?
lag_function = "#{Gitlab::Database.pg_wal_lsn_diff}" \
"(#{Gitlab::Database.pg_current_wal_insert_lsn}(), restart_lsn)::bigint"
lag_function = "pg_wal_lsn_diff" \
"(pg_current_wal_insert_lsn(), restart_lsn)::bigint"
# We force the use of a transaction here so the query always goes to the
# primary, even when using the EE DB load balancer.

View file

@ -1,4 +1,5 @@
- add_page_startup_api_call discussions_path(@issue)
- add_page_startup_api_call notes_url
- @gfm_form = true

View file

@ -228,13 +228,13 @@ which ideally should not have Redis or Sentinels in the same machine:
sentinels:
-
host: 10.0.0.1
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
-
host: 10.0.0.2
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
-
host: 10.0.0.3
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
```
1. [Restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
@ -353,13 +353,13 @@ or a failover promotes a different **Primary** node.
sentinels:
-
host: 10.0.0.1
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
-
host: 10.0.0.2
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
-
host: 10.0.0.3
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
```
1. [Restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.

View file

@ -146,13 +146,13 @@ production:
sentinels:
-
host: 10.0.0.1
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
-
host: 10.0.0.2
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
-
host: 10.0.0.3
port: 26379 # point to sentinel, not to redis port
port: 26379 # point to sentinel, not to redis port
```
When in doubt, read the [Redis Sentinel documentation](https://redis.io/topics/sentinel).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/using_a_geo_server.md'
---
This document was moved to [another location](../administration/geo/replication/using_a_geo_server.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/disaster_recovery/bring_primary_back.md'
---
This document was moved to [another location](../administration/geo/disaster_recovery/bring_primary_back.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/configuration.md'
---
This document was moved to [another location](../administration/geo/replication/configuration.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/configuration.md'
---
This document was moved to [another location](../administration/geo/replication/configuration.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/setup/database.md'
---
This document was moved to [another location](../administration/geo/setup/database.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/setup/database.md'
---
This document was moved to [another location](../administration/geo/setup/database.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/disaster_recovery/index.md'
---
This document was moved to [another location](../administration/geo/disaster_recovery/index.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/docker_registry.md'
---
This document was moved to [another location](../administration/geo/replication/docker_registry.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/faq.md'
---
This document was moved to [another location](../administration/geo/replication/faq.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/multiple_servers.md'
---
This document was moved to [another location](../administration/geo/replication/multiple_servers.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/object_storage.md'
---
This document was moved to [another location](../administration/geo/replication/object_storage.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/disaster_recovery/planned_failover.md'
---
This document was moved to [another location](../administration/geo/disaster_recovery/planned_failover.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/security_review.md'
---
This document was moved to [another location](../administration/geo/replication/security_review.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/operations/fast_ssh_key_lookup.md'
---
This document was moved to [another location](../administration/operations/fast_ssh_key_lookup.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/troubleshooting.md'
---
This document was moved to [another location](../administration/geo/replication/troubleshooting.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/tuning.md'
---
This document was moved to [another location](../administration/geo/replication/tuning.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/updating_the_geo_nodes.md'
---
This document was moved to [another location](../administration/geo/replication/updating_the_geo_nodes.md).

View file

@ -1,5 +0,0 @@
---
redirect_to: '../administration/geo/replication/using_a_geo_server.md'
---
This document was moved to [another location](../administration/geo/replication/using_a_geo_server.md).

View file

@ -45,10 +45,10 @@ To enable the CAS OmniAuth provider you must register your application with your
- { name: 'cas3',
label: 'cas',
args: {
url: 'CAS_SERVER',
login_url: '/CAS_PATH/login',
service_validate_url: '/CAS_PATH/p3/serviceValidate',
logout_url: '/CAS_PATH/logout'} }
url: 'CAS_SERVER',
login_url: '/CAS_PATH/login',
service_validate_url: '/CAS_PATH/p3/serviceValidate',
logout_url: '/CAS_PATH/logout' } }
```
1. Change 'CAS_PATH' to the root of your CAS instance (ie. `cas`).

View file

@ -83,7 +83,7 @@ To enable the Facebook OmniAuth provider you must register your application with
```yaml
- { name: 'facebook', app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET' }
app_secret: 'YOUR_APP_SECRET' }
```
1. Change 'YOUR_APP_ID' to the API key from Facebook page in step 10.

View file

@ -71,17 +71,18 @@ Follow these steps to incorporate the GitHub OAuth 2 app in your GitLab server:
```yaml
- { name: 'github', app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { scope: 'user:email' } }
app_secret: 'YOUR_APP_SECRET',
args: { scope: 'user:email' } }
```
For GitHub Enterprise:
```yaml
- { name: 'github', app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
url: "https://github.example.com/",
args: { scope: 'user:email' } }
- { name: 'github',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
url: "https://github.example.com/",
args: { scope: 'user:email' } }
```
**Replace `https://github.example.com/` with your GitHub URL.**
@ -125,11 +126,12 @@ omnibus_gitconfig['system'] = { "http" => ["sslVerify = false"] }
For installation from source:
```yaml
- { name: 'github', app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
url: "https://github.example.com/",
verify_ssl: false,
args: { scope: 'user:email' } }
- { name: 'github',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
url: "https://github.example.com/",
verify_ssl: false,
args: { scope: 'user:email' } }
```
You will also need to disable Git SSL verification on the server hosting GitLab.

View file

@ -63,9 +63,10 @@ GitLab.com will generate an application ID and secret key for you to use.
For installations from source:
```yaml
- { name: 'gitlab', app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { scope: 'api' } }
- { name: 'gitlab',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { scope: 'api' } }
```
1. Change 'YOUR_APP_ID' to the Application ID from the GitLab.com application page.

View file

@ -84,9 +84,10 @@ On your GitLab server:
For installations from source:
```yaml
- { name: 'google_oauth2', app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { access_type: 'offline', approval_prompt: '' } }
- { name: 'google_oauth2',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { access_type: 'offline', approval_prompt: '' } }
```
1. Change `YOUR_APP_ID` to the client ID from the Google Developer page

View file

@ -207,9 +207,10 @@ remove the OmniAuth provider named `kerberos` from your `gitlab.yml` /
```yaml
omniauth:
# Rest of configuration omitted
# ...
providers:
- { name: 'kerberos' } # <-- remove this line
- { name: 'kerberos' } # <-- remove this line
```
1. [Restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect.

View file

@ -104,21 +104,21 @@ To change these settings:
```yaml
## OmniAuth settings
omniauth:
# Allow login via Twitter, Google, etc. using OmniAuth providers
# Versions prior to 11.4 require this to be set to true
# enabled: true
omniauth:
# Allow login via Twitter, Google, etc. using OmniAuth providers
# Versions prior to 11.4 require this to be set to true
# enabled: true
# CAUTION!
# This allows users to login without having a user account first. Define the allowed providers
# using an array, e.g. ["saml", "twitter"], or as true/false to allow all providers or none.
# User accounts will be created automatically when authentication was successful.
allow_single_sign_on: ["saml", "twitter"]
# CAUTION!
# This allows users to login without having a user account first. Define the allowed providers
# using an array, e.g. ["saml", "twitter"], or as true/false to allow all providers or none.
# User accounts will be created automatically when authentication was successful.
allow_single_sign_on: ["saml", "twitter"]
auto_link_ldap_user: true
auto_link_ldap_user: true
# Locks down those users until they have been cleared by the admin (default: true).
block_auto_created_users: true
# Locks down those users until they have been cleared by the admin (default: true).
block_auto_created_users: true
```
Now we can choose one or more of the [Supported Providers](#supported-providers)
@ -142,7 +142,7 @@ The chosen OmniAuth provider is now active and can be used to sign in to GitLab
## Automatically Link Existing Users to OmniAuth Users
> [Introduced in GitLab 13.4.](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36664)
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36664) in GitLab 13.4.
You can automatically link OmniAuth users with existing GitLab users if their email addresses match.
For example, the following setting is used to enable the auto link feature for both a SAML provider and the Twitter OAuth provider:

View file

@ -64,7 +64,7 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
- { name: 'salesforce',
app_id: 'SALESFORCE_CLIENT_ID',
app_secret: 'SALESFORCE_CLIENT_SECRET'
}
}
```
1. Change `SALESFORCE_CLIENT_ID` to the Consumer Key from the Salesforce connected application page.

View file

@ -113,16 +113,16 @@ in your SAML IdP:
omniauth:
providers:
- {
name: 'saml',
args: {
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
},
label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
}
name: 'saml',
args: {
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
},
label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
}
```
1. Change the value for `assertion_consumer_service_url` to match the HTTPS endpoint
@ -210,7 +210,7 @@ Example:
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
} }
} }
```
### External Groups **(STARTER ONLY)**
@ -228,7 +228,7 @@ SAML login supports automatic identification on whether a user should be conside
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
} }
} }
```
### Admin Groups **(STARTER ONLY)**
@ -248,7 +248,7 @@ considered admin users.
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
} }
} }
```
### Auditor Groups **(STARTER ONLY)**
@ -270,7 +270,7 @@ considered auditor users.
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
} }
} }
```
## Bypass two factor authentication
@ -328,22 +328,22 @@ In addition to the changes in GitLab, make sure that your IdP is returning the
omniauth:
providers:
- {
name: 'saml',
args: {
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
upstream_two_factor_authn_contexts:
[
'urn:oasis:names:tc:SAML:2.0:ac:classes:CertificateProtectedTransport',
'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS',
'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN'
]
},
label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
}
name: 'saml',
args: {
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
upstream_two_factor_authn_contexts:
[
'urn:oasis:names:tc:SAML:2.0:ac:classes:CertificateProtectedTransport',
'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS',
'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN'
]
},
label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
}
```
1. Save the file and [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect
@ -436,7 +436,7 @@ args: {
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
attribute_statements: { email: ['EmailAddress'] },
allowed_clock_drift: 1 # for one second clock drift
allowed_clock_drift: 1 # for one second clock drift
}
```
@ -561,10 +561,10 @@ args: {
<redacted>
-----END PRIVATE KEY-----',
security: {
authn_requests_signed: true, # enable signature on AuthNRequest
want_assertions_signed: true, # enable the requirement of signed assertion
embed_sign: true, # embedded signature or HTTP GET parameter signature
metadata_signed: false, # enable signature on Metadata
authn_requests_signed: true, # enable signature on AuthNRequest
want_assertions_signed: true, # enable the requirement of signed assertion
embed_sign: true, # embedded signature or HTTP GET parameter signature
metadata_signed: false, # enable signature on Metadata
signature_method: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
digest_method: 'http://www.w3.org/2001/04/xmlenc#sha256',
}
@ -629,9 +629,9 @@ Group SAML on a self-managed instance is limited when compared to the recommende
```yaml
omniauth:
enabled: true
providers:
- { name: 'group_saml' }
enabled: true
providers:
- { name: 'group_saml' }
```
## Troubleshooting

View file

@ -65,7 +65,8 @@ To enable the Twitter OmniAuth provider you must register your application with
For installations from source:
```yaml
- { name: 'twitter', app_id: 'YOUR_APP_ID',
- { name: 'twitter',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET' }
```

View file

@ -70,7 +70,8 @@ receivers:
bearer_token: 9e1cbfcd546896a9ea8be557caf13a76
send_resolved: true
url: http://192.168.178.31:3001/root/manual_prometheus/prometheus/alerts/notify.json
...
# Rest of configuration omitted
# ...
```
For GitLab to associate your alerts with an [environment](../../ci/environments/index.md),

View file

@ -17,7 +17,7 @@ dashboard: 'Dashboard Title'
panel_groups:
- group: 'Group Title'
panels:
- type: area-chart # or line-chart
- type: area-chart # or line-chart
title: 'Area Chart Title'
y_label: 'Y-Axis'
y_axis:

View file

@ -317,7 +317,7 @@ metadata:
name: gitlab-managed-apps-default-proxy
namespace: gitlab-managed-apps
spec:
env:
env:
- name: http_proxy
value: "PUT_YOUR_HTTP_PROXY_HERE"
- name: https_proxy

View file

@ -125,27 +125,27 @@ the Agent in subsequent steps. You can create an Agent record either:
- Through GraphQL: **(PREMIUM ONLY)**
```json
mutation createAgent {
createClusterAgent(input: { projectPath: "path-to/your-awesome-project", name: "<agent-name>" }) {
clusterAgent {
id
name
}
errors
```graphql
mutation createAgent {
createClusterAgent(input: { projectPath: "path-to/your-awesome-project", name: "<agent-name>" }) {
clusterAgent {
id
name
}
errors
}
}
mutation createToken {
clusterAgentTokenCreate(input: { clusterAgentId: <cluster-agent-id-taken-from-the-previous-mutation> }) {
secret # This is the value you need to use on the next step
token {
createdAt
id
}
errors
mutation createToken {
clusterAgentTokenCreate(input: { clusterAgentId: <cluster-agent-id-taken-from-the-previous-mutation> }) {
secret # This is the value you need to use on the next step
token {
createdAt
id
}
errors
}
}
```
NOTE: **Note:**
@ -245,7 +245,7 @@ spec:
args:
- --token-file=/config/token
- --kas-address
- grpc://host.docker.internal:5005 # {"$openapi":"kas-address"}
- grpc://host.docker.internal:5005 # {"$openapi":"kas-address"}
volumeMounts:
- name: token-volume
mountPath: /config

View file

@ -269,7 +269,7 @@ To add a Kubernetes cluster to your project, group, or instance:
Copy the `<authentication_token>` value from the output:
```yaml
```plaintext
Name: gitlab-token-b5zv4
Namespace: kube-system
Labels: <none>

View file

@ -222,7 +222,8 @@ the environment of the deployed function:
```yaml
provider:
...
# Other configuration omitted
# ...
environment:
A_VARIABLE: ${env:A_VARIABLE}
```
@ -245,10 +246,10 @@ functions:
hello:
handler: src/handler.hello
events:
- http: # Rewrite this part to enable CORS
- http: # Rewrite this part to enable CORS
path: hello
method: get
cors: true # <-- CORS here
cors: true # <-- CORS here
```
You also need to return CORS specific headers in your function response:

View file

@ -92,10 +92,6 @@ module Gitlab
@version ||= database_version.match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
end
def self.postgresql_9_or_less?
version.to_f < 10
end
def self.postgresql_minimum_supported_version?
version.to_f >= MINIMUM_POSTGRES_VERSION
end
@ -127,28 +123,6 @@ module Gitlab
# ignore - happens when Rake tasks yet have to create a database, e.g. for testing
end
# map some of the function names that changed between PostgreSQL 9 and 10
# https://wiki.postgresql.org/wiki/New_in_postgres_10
def self.pg_wal_lsn_diff
Gitlab::Database.postgresql_9_or_less? ? 'pg_xlog_location_diff' : 'pg_wal_lsn_diff'
end
def self.pg_current_wal_insert_lsn
Gitlab::Database.postgresql_9_or_less? ? 'pg_current_xlog_insert_location' : 'pg_current_wal_insert_lsn'
end
def self.pg_last_wal_receive_lsn
Gitlab::Database.postgresql_9_or_less? ? 'pg_last_xlog_receive_location' : 'pg_last_wal_receive_lsn'
end
def self.pg_last_wal_replay_lsn
Gitlab::Database.postgresql_9_or_less? ? 'pg_last_xlog_replay_location' : 'pg_last_wal_replay_lsn'
end
def self.pg_last_xact_replay_timestamp
'pg_last_xact_replay_timestamp'
end
def self.nulls_last_order(field, direction = 'ASC')
Arel.sql("#{field} #{direction} NULLS LAST")
end

View file

@ -2686,6 +2686,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
msgid "An error occured while making the changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
msgstr ""
@ -2959,9 +2962,6 @@ msgstr ""
msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr ""
msgid "An error occurred while searching for milestones"
msgstr ""
@ -9527,6 +9527,9 @@ msgstr ""
msgid "Emails sent from Service Desk will have this name"
msgstr ""
msgid "Emails sent to %{email} will still be supported"
msgstr ""
msgid "Emails separated by comma"
msgstr ""

View file

@ -48,7 +48,10 @@ describe('AddIssuableForm', () => {
const input = findFormInput(wrapper);
if (input) input.blur();
wrapper.destroy();
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
describe('with data', () => {

View file

@ -1,241 +1,146 @@
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import { PathIdSeparator } from '~/related_issues/constants';
import issueToken from '~/related_issues/components/issue_token.vue';
import IssueToken from '~/related_issues/components/issue_token.vue';
describe('IssueToken', () => {
const idKey = 200;
const displayReference = 'foo/bar#123';
const title = 'some title';
const pathIdSeparator = PathIdSeparator.Issue;
const eventNamespace = 'pendingIssuable';
let IssueToken;
let vm;
const path = '/foo/bar/issues/123';
const pathIdSeparator = PathIdSeparator.Issue;
const title = 'some title';
beforeEach(() => {
IssueToken = Vue.extend(issueToken);
});
let wrapper;
const defaultProps = {
idKey,
displayReference,
pathIdSeparator,
};
const createComponent = (props = {}) => {
wrapper = shallowMount(IssueToken, {
propsData: { ...defaultProps, ...props },
});
};
afterEach(() => {
if (vm) {
vm.$destroy();
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
const findLink = () => wrapper.find({ ref: 'link' });
const findReference = () => wrapper.find({ ref: 'reference' });
const findReferenceIcon = () => wrapper.find('[data-testid="referenceIcon"]');
const findRemoveBtn = () => wrapper.find('[data-testid="removeBtn"]');
const findTitle = () => wrapper.find({ ref: 'title' });
describe('with reference supplied', () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
},
}).$mount();
createComponent();
});
it('shows reference', () => {
expect(vm.$el.textContent.trim()).toEqual(displayReference);
expect(wrapper.text()).toContain(displayReference);
});
it('does not link without path specified', () => {
expect(vm.$refs.link.tagName.toLowerCase()).toEqual('span');
expect(vm.$refs.link.getAttribute('href')).toBeNull();
expect(findLink().element.tagName).toBe('SPAN');
expect(findLink().attributes('href')).toBeUndefined();
});
});
describe('with reference and title supplied', () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
title,
},
}).$mount();
});
it('shows reference and title', () => {
expect(vm.$refs.reference.textContent.trim()).toEqual(displayReference);
expect(vm.$refs.title.textContent.trim()).toEqual(title);
createComponent({
title,
});
expect(findReference().text()).toBe(displayReference);
expect(findTitle().text()).toBe(title);
});
});
describe('with path supplied', () => {
const path = '/foo/bar/issues/123';
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
title,
path,
},
}).$mount();
});
describe('with path and title supplied', () => {
it('links reference and title', () => {
expect(vm.$refs.link.getAttribute('href')).toEqual(path);
createComponent({
path,
title,
});
expect(findLink().attributes('href')).toBe(path);
});
});
describe('with state supplied', () => {
describe("`state: 'opened'`", () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
state: 'opened',
},
}).$mount();
it.each`
state | icon | cssClass
${'opened'} | ${'issue-open-m'} | ${'issue-token-state-icon-open'}
${'reopened'} | ${'issue-open-m'} | ${'issue-token-state-icon-open'}
${'closed'} | ${'issue-close'} | ${'issue-token-state-icon-closed'}
`('shows "$icon" icon when "$state"', ({ state, icon, cssClass }) => {
createComponent({
path,
state,
});
it('shows green circle icon', () => {
expect(vm.$el.querySelector('.issue-token-state-icon-open.fa.fa-circle-o')).toBeDefined();
});
});
describe("`state: 'reopened'`", () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
state: 'reopened',
},
}).$mount();
});
it('shows green circle icon', () => {
expect(vm.$el.querySelector('.issue-token-state-icon-open.fa.fa-circle-o')).toBeDefined();
});
});
describe("`state: 'closed'`", () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
state: 'closed',
},
}).$mount();
});
it('shows red minus icon', () => {
expect(vm.$el.querySelector('.issue-token-state-icon-closed.fa.fa-minus')).toBeDefined();
});
expect(findReferenceIcon().props('name')).toBe(icon);
expect(findReferenceIcon().classes()).toContain(cssClass);
});
});
describe('with reference, title, state', () => {
const state = 'opened';
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
title,
state,
},
}).$mount();
});
it('shows reference, title, and state', () => {
const stateIcon = vm.$refs.reference.querySelector('svg');
createComponent({
title,
state,
});
expect(stateIcon.getAttribute('aria-label')).toEqual(state);
expect(vm.$refs.reference.textContent.trim()).toEqual(displayReference);
expect(vm.$refs.title.textContent.trim()).toEqual(title);
expect(findReferenceIcon().attributes('aria-label')).toBe(state);
expect(findReference().text()).toBe(displayReference);
expect(findTitle().text()).toBe(title);
});
});
describe('with canRemove', () => {
describe('`canRemove: false` (default)', () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
},
}).$mount();
});
it('does not have remove button', () => {
expect(vm.$el.querySelector('.issue-token-remove-button')).toBeNull();
createComponent();
expect(findRemoveBtn().exists()).toBe(false);
});
});
describe('`canRemove: true`', () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
canRemove: true,
},
}).$mount();
createComponent({
eventNamespace,
canRemove: true,
});
});
it('has remove button', () => {
expect(vm.$el.querySelector('.issue-token-remove-button')).toBeDefined();
expect(findRemoveBtn().exists()).toBe(true);
});
it('emits event when clicked', () => {
findRemoveBtn().trigger('click');
const emitted = wrapper.emitted(`${eventNamespace}RemoveRequest`);
expect(emitted).toHaveLength(1);
expect(emitted[0]).toEqual([idKey]);
});
it('tooltip should not be escaped', () => {
expect(findRemoveBtn().attributes('data-original-title')).toBe(
`Remove ${displayReference}`,
);
});
});
});
describe('methods', () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
},
}).$mount();
});
it('when getting checked', () => {
jest.spyOn(vm, '$emit').mockImplementation(() => {});
vm.onRemoveRequest();
expect(vm.$emit).toHaveBeenCalledWith('pendingIssuableRemoveRequest', vm.idKey);
});
});
describe('tooltip', () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
idKey,
eventNamespace,
displayReference,
pathIdSeparator,
canRemove: true,
},
}).$mount();
});
it('should not be escaped', () => {
const { originalTitle } = vm.$refs.removeButton.dataset;
expect(originalTitle).toEqual(`Remove ${displayReference}`);
});
});
});

View file

@ -18,7 +18,10 @@ describe('RelatedIssuesBlock', () => {
const findIssueCountBadgeAddButton = () => wrapper.find(GlButton);
afterEach(() => {
wrapper.destroy();
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
describe('with defaults', () => {

View file

@ -14,7 +14,10 @@ describe('RelatedIssuesList', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
describe('with defaults', () => {

View file

@ -218,9 +218,7 @@ describe('ServiceDeskRoot', () => {
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(wrapper.html()).toContain(
'An error occurred while saving the template. Please check if the template exists.',
);
expect(wrapper.html()).toContain('An error occured while making the changes:');
});
});
});

View file

@ -70,25 +70,6 @@ RSpec.describe Gitlab::Database do
end
end
describe '.postgresql_9_or_less?' do
it 'returns true when using postgresql 8.4' do
allow(described_class).to receive(:version).and_return('8.4')
expect(described_class.postgresql_9_or_less?).to eq(true)
end
it 'returns true when using PostgreSQL 9.6' do
allow(described_class).to receive(:version).and_return('9.6')
expect(described_class.postgresql_9_or_less?).to eq(true)
end
it 'returns false when using PostgreSQL 10 or newer' do
allow(described_class).to receive(:version).and_return('10')
expect(described_class.postgresql_9_or_less?).to eq(false)
end
end
describe '.postgresql_minimum_supported_version?' do
it 'returns false when using PostgreSQL 10' do
allow(described_class).to receive(:version).and_return('10')
@ -150,68 +131,6 @@ RSpec.describe Gitlab::Database do
end
end
describe '.pg_wal_lsn_diff' do
it 'returns old name when using PostgreSQL 9.6' do
allow(described_class).to receive(:version).and_return('9.6')
expect(described_class.pg_wal_lsn_diff).to eq('pg_xlog_location_diff')
end
it 'returns new name when using PostgreSQL 10 or newer' do
allow(described_class).to receive(:version).and_return('10')
expect(described_class.pg_wal_lsn_diff).to eq('pg_wal_lsn_diff')
end
end
describe '.pg_current_wal_insert_lsn' do
it 'returns old name when using PostgreSQL 9.6' do
allow(described_class).to receive(:version).and_return('9.6')
expect(described_class.pg_current_wal_insert_lsn).to eq('pg_current_xlog_insert_location')
end
it 'returns new name when using PostgreSQL 10 or newer' do
allow(described_class).to receive(:version).and_return('10')
expect(described_class.pg_current_wal_insert_lsn).to eq('pg_current_wal_insert_lsn')
end
end
describe '.pg_last_wal_receive_lsn' do
it 'returns old name when using PostgreSQL 9.6' do
allow(described_class).to receive(:version).and_return('9.6')
expect(described_class.pg_last_wal_receive_lsn).to eq('pg_last_xlog_receive_location')
end
it 'returns new name when using PostgreSQL 10 or newer' do
allow(described_class).to receive(:version).and_return('10')
expect(described_class.pg_last_wal_receive_lsn).to eq('pg_last_wal_receive_lsn')
end
end
describe '.pg_last_wal_replay_lsn' do
it 'returns old name when using PostgreSQL 9.6' do
allow(described_class).to receive(:version).and_return('9.6')
expect(described_class.pg_last_wal_replay_lsn).to eq('pg_last_xlog_replay_location')
end
it 'returns new name when using PostgreSQL 10 or newer' do
allow(described_class).to receive(:version).and_return('10')
expect(described_class.pg_last_wal_replay_lsn).to eq('pg_last_wal_replay_lsn')
end
end
describe '.pg_last_xact_replay_timestamp' do
it 'returns pg_last_xact_replay_timestamp' do
expect(described_class.pg_last_xact_replay_timestamp).to eq('pg_last_xact_replay_timestamp')
end
end
describe '.nulls_last_order' do
it { expect(described_class.nulls_last_order('column', 'ASC')).to eq 'column ASC NULLS LAST'}
it { expect(described_class.nulls_last_order('column', 'DESC')).to eq 'column DESC NULLS LAST'}