summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-29 18:09:11 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-29 18:09:11 +0000
commitce27ba9f6c36ecb36114887853a5820c83a7036c (patch)
tree5ea0441efc567f75ca0e23d61fdec9ae426b37d7
parent4dfd78cb55b08ab20124187d1aab6a431da3e302 (diff)
downloadgitlab-ce-ce27ba9f6c36ecb36114887853a5820c83a7036c.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue19
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue46
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql9
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql11
-rw-r--r--app/assets/javascripts/alerts_settings/index.js20
-rw-r--r--app/assets/javascripts/feature_flags/components/edit_feature_flag.vue2
-rw-r--r--app/assets/javascripts/pages/admin/runners/index.js13
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js24
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js46
-rw-r--r--app/assets/javascripts/pages/shared/mount_runner_instructions.js32
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue5
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_area.vue15
-rw-r--r--app/assets/javascripts/static_site_editor/services/front_matterify.js2
-rw-r--r--app/assets/javascripts/static_site_editor/services/parse_source_file.js18
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql20
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql16
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue214
-rw-r--r--app/assets/stylesheets/pages/incident_management_list.scss19
-rw-r--r--app/controllers/profiles_controller.rb2
-rw-r--r--app/graphql/types/availability_enum.rb12
-rw-r--r--app/graphql/types/terraform/state_type.rb5
-rw-r--r--app/graphql/types/terraform/state_version_type.rb29
-rw-r--r--app/graphql/types/user_status_type.rb2
-rw-r--r--app/helpers/operations_helper.rb3
-rw-r--r--app/models/deployment_merge_request.rb5
-rw-r--r--app/models/terraform/state.rb11
-rw-r--r--app/models/user_status.rb2
-rw-r--r--app/policies/terraform/state_version_policy.rb9
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_service.rb2
-rw-r--r--app/services/users/set_status_service.rb5
-rw-r--r--app/views/admin/runners/index.html.haml4
-rw-r--r--app/views/ci/runner/_how_to_setup_runner.html.haml2
-rw-r--r--app/views/groups/runners/_group_runners.html.haml4
-rw-r--r--app/views/projects/runners/_specific_runners.html.haml4
-rwxr-xr-xbin/background_jobs2
-rwxr-xr-xbin/mail_room2
-rwxr-xr-xbin/web_unicorn2
-rw-r--r--changelogs/unreleased/267147-terraform-state-versions-graphql.yml5
-rw-r--r--changelogs/unreleased/271550-fj-forbid-realtime_changes-in-robots.yml5
-rw-r--r--changelogs/unreleased/ImproveShellScriptsChangeDirException.yml5
-rw-r--r--changelogs/unreleased/feature-flags-edit-increase-loading-icon-size.yml5
-rw-r--r--changelogs/unreleased/jivanvl-runner-guided-install-frontend.yml5
-rw-r--r--changelogs/unreleased/job-dropdown-click.yml5
-rw-r--r--changelogs/unreleased/set-user-availability-be.yml5
-rw-r--r--config/feature_flags/development/lfs_link_existing_object.yml7
-rw-r--r--db/migrate/20201022103304_add_availability_to_user_statuses.rb9
-rw-r--r--db/schema_migrations/202010221033041
-rw-r--r--db/structure.sql3
-rw-r--r--doc/.vale/gitlab/Acronyms.yml1
-rw-r--r--doc/administration/geo/index.md1
-rw-r--r--doc/administration/geo/replication/troubleshooting.md10
-rw-r--r--doc/administration/operations/moving_repositories.md48
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql47
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json136
-rw-r--r--doc/api/graphql/reference/index.md20
-rw-r--r--doc/api/project_repository_storage_moves.md4
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md4
-rw-r--r--doc/operations/incident_management/incidents.md48
-rw-r--r--doc/update/README.md4
-rw-r--r--doc/user/group/index.md7
-rw-r--r--doc/user/project/clusters/index.md3
-rw-r--r--lib/api/discussions.rb20
-rw-r--r--lib/api/entities/user_status.rb1
-rw-r--r--lib/api/helpers/discussions_helpers.rb9
-rw-r--r--lib/api/helpers/notes_helpers.rb10
-rw-r--r--lib/api/import_bitbucket_server.rb2
-rw-r--r--lib/api/import_github.rb2
-rw-r--r--lib/api/issue_links.rb2
-rw-r--r--lib/api/issues.rb4
-rw-r--r--lib/api/job_artifacts.rb2
-rw-r--r--lib/api/jobs.rb2
-rw-r--r--lib/api/keys.rb2
-rw-r--r--lib/api/labels.rb2
-rw-r--r--lib/api/lint.rb2
-rw-r--r--lib/api/markdown.rb2
-rw-r--r--lib/api/members.rb2
-rw-r--r--lib/api/merge_request_approvals.rb2
-rw-r--r--lib/api/merge_request_diffs.rb2
-rw-r--r--lib/api/merge_requests.rb2
-rw-r--r--lib/api/metrics/dashboard/annotations.rb2
-rw-r--r--lib/api/metrics/user_starred_dashboards.rb2
-rw-r--r--lib/api/namespaces.rb2
-rw-r--r--lib/api/notes.rb10
-rw-r--r--lib/api/users.rb1
-rw-r--r--lib/gitlab/repository_size_checker.rb4
-rw-r--r--locale/gitlab.pot24
-rw-r--r--package.json2
-rw-r--r--public/robots.txt1
-rwxr-xr-xscripts/lint-doc.sh2
-rw-r--r--spec/controllers/profiles_controller_spec.rb3
-rw-r--r--spec/factories/terraform/state.rb2
-rw-r--r--spec/frontend/alerts_settings/alerts_integrations_list_spec.js4
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_form_new_spec.js2
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js55
-rw-r--r--spec/frontend/alerts_settings/mocks/integrations.json38
-rw-r--r--spec/frontend/static_site_editor/services/front_matterify_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/mock_data.js107
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js119
-rw-r--r--spec/graphql/types/availability_enum_spec.rb11
-rw-r--r--spec/graphql/types/terraform/state_type_spec.rb5
-rw-r--r--spec/graphql/types/terraform/state_version_type_spec.rb19
-rw-r--r--spec/graphql/types/user_status_type_spec.rb1
-rw-r--r--spec/helpers/operations_helper_spec.rb3
-rw-r--r--spec/lib/api/every_api_endpoint_spec.rb9
-rw-r--r--spec/policies/terraform/state_version_policy_spec.rb33
-rw-r--r--spec/requests/api/graphql/project/terraform/states_spec.rb25
-rw-r--r--spec/requests/api/graphql/user_query_spec.rb9
-rw-r--r--spec/requests/robots_txt_spec.rb4
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb12
-rw-r--r--spec/services/users/set_status_service_spec.rb23
-rw-r--r--spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb59
-rw-r--r--yarn.lock142
112 files changed, 1586 insertions, 253 deletions
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
index d377f0f2654..432271d2075 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTable, GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlTable, GlIcon, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import { s__, __ } from '~/locale';
import Tracking from '~/tracking';
import { trackAlertIntegrationsViewsOptions } from '../constants';
@@ -27,6 +27,7 @@ export default {
components: {
GlTable,
GlIcon,
+ GlLoadingIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -37,10 +38,15 @@ export default {
required: false,
default: () => [],
},
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
fields: [
{
- key: 'activated',
+ key: 'active',
label: __('Status'),
},
{
@@ -78,12 +84,13 @@ export default {
:empty-text="$options.i18n.emptyState"
:items="integrations"
:fields="$options.fields"
+ :busy="loading"
stacked="md"
:tbody-tr-class="tbodyTrClass"
show-empty
>
- <template #cell(activated)="{ item }">
- <span v-if="item.activated" data-testid="integration-activated-status">
+ <template #cell(active)="{ item }">
+ <span v-if="item.active" data-testid="integration-activated-status">
<gl-icon
v-gl-tooltip
name="check-circle-filled"
@@ -104,6 +111,10 @@ export default {
{{ $options.i18n.status.disabled.name }}
</span>
</template>
+
+ <template #table-busy>
+ <gl-loading-icon size="lg" color="dark" class="mt-3" />
+ </template>
</gl-table>
</div>
</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
index 1edb8f1c921..1576faf13a9 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
@@ -1,6 +1,8 @@
<script>
import { s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { fetchPolicies } from '~/lib/graphql';
+import getIntegrationsQuery from '../graphql/queries/get_integrations.query.graphql';
import IntegrationsList from './alerts_integrations_list.vue';
import SettingsFormOld from './alerts_settings_form_old.vue';
import SettingsFormNew from './alerts_settings_form_new.vue';
@@ -19,19 +21,52 @@ export default {
prometheus: {
default: {},
},
+ projectPath: {
+ default: '',
+ },
+ },
+ apollo: {
+ integrations: {
+ fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
+ query: getIntegrationsQuery,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ };
+ },
+ update(data) {
+ const { alertManagementIntegrations: { nodes: list = [] } = {} } = data.project || {};
+
+ return {
+ list,
+ };
+ },
+ error() {
+ this.errored = true;
+ },
+ },
+ },
+ data() {
+ return {
+ errored: false,
+ integrations: {},
+ };
},
computed: {
- integrations() {
+ loading() {
+ return this.$apollo.queries.integrations.loading;
+ },
+ intergrationsOptionsOld() {
return [
{
name: s__('AlertSettings|HTTP endpoint'),
type: s__('AlertsIntegrations|HTTP endpoint'),
- activated: this.generic.activated,
+ active: this.generic.activated,
},
{
name: s__('AlertSettings|External Prometheus'),
type: s__('AlertsIntegrations|Prometheus'),
- activated: this.prometheus.activated,
+ active: this.prometheus.activated,
},
];
},
@@ -41,7 +76,10 @@ export default {
<template>
<div>
- <integrations-list :integrations="integrations" />
+ <integrations-list
+ :integrations="glFeatures.httpIntegrationsList ? integrations.list : intergrationsOptionsOld"
+ :loading="loading"
+ />
<settings-form-new v-if="glFeatures.httpIntegrationsList" />
<settings-form-old v-else />
</div>
diff --git a/app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql b/app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql
new file mode 100644
index 00000000000..6d9307959df
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql
@@ -0,0 +1,9 @@
+fragment IntegrationItem on AlertManagementIntegration {
+ id
+ type
+ active
+ name
+ url
+ token
+ apiUrl
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
new file mode 100644
index 00000000000..228dd5fb176
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
@@ -0,0 +1,11 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+query getIntegrations($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ alertManagementIntegrations {
+ nodes {
+ ...IntegrationItem
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js
index 80f06a094b7..8f22b8d1dcd 100644
--- a/app/assets/javascripts/alerts_settings/index.js
+++ b/app/assets/javascripts/alerts_settings/index.js
@@ -1,7 +1,11 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import AlertSettingsWrapper from './components/alerts_settings_wrapper.vue';
+Vue.use(VueApollo);
+
export default el => {
if (!el) {
return null;
@@ -24,8 +28,22 @@ export default el => {
opsgenieMvcFormPath,
opsgenieMvcEnabled,
opsgenieMvcTargetUrl,
+ projectPath,
} = el.dataset;
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ cacheConfig: {},
+ },
+ ),
+ });
+
+ apolloProvider.clients.defaultClient.cache.writeData({
+ data: {},
+ });
+
return new Vue({
el,
provide: {
@@ -51,7 +69,9 @@ export default el => {
opsgenieMvcTargetUrl,
opsgenieMvcIsAvailable: parseBoolean(opsgenieMvcAvailable),
},
+ projectPath,
},
+ apolloProvider,
components: {
AlertSettingsWrapper,
},
diff --git a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
index 26b18f9bf5a..9ec65bb0b43 100644
--- a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
+++ b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
@@ -103,7 +103,7 @@ export default {
>
{{ $options.translations.newFlagAlert }}
</gl-alert>
- <gl-loading-icon v-if="isLoading" />
+ <gl-loading-icon v-if="isLoading" size="xl" class="gl-mt-7" />
<template v-else-if="!isLoading && !hasError">
<gl-alert v-if="deprecatedAndEditable" variant="warning" :dismissible="false" class="gl-my-5">
diff --git a/app/assets/javascripts/pages/admin/runners/index.js b/app/assets/javascripts/pages/admin/runners/index.js
index e60c6133c7c..104b7eeaf96 100644
--- a/app/assets/javascripts/pages/admin/runners/index.js
+++ b/app/assets/javascripts/pages/admin/runners/index.js
@@ -1,11 +1,12 @@
import initFilteredSearch from '~/pages/search/init_filtered_search';
import AdminRunnersFilteredSearchTokenKeys from '~/filtered_search/admin_runners_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
-document.addEventListener('DOMContentLoaded', () => {
- initFilteredSearch({
- page: FILTERED_SEARCH.ADMIN_RUNNERS,
- filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys,
- useDefaultState: true,
- });
+initFilteredSearch({
+ page: FILTERED_SEARCH.ADMIN_RUNNERS,
+ filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys,
+ useDefaultState: true,
});
+
+initInstallRunner();
diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
index e8d8c985ade..3456048d718 100644
--- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
@@ -4,18 +4,18 @@ import initFilteredSearch from '~/pages/search/init_filtered_search';
import GroupRunnersFilteredSearchTokenKeys from '~/filtered_search/group_runners_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
import initSharedRunnersForm from '~/group_settings/mount_shared_runners';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
-document.addEventListener('DOMContentLoaded', () => {
- // Initialize expandable settings panels
- initSettingsPanels();
+// Initialize expandable settings panels
+initSettingsPanels();
- initFilteredSearch({
- page: FILTERED_SEARCH.ADMIN_RUNNERS,
- filteredSearchTokenKeys: GroupRunnersFilteredSearchTokenKeys,
- anchor: FILTERED_SEARCH.GROUP_RUNNERS_ANCHOR,
- useDefaultState: false,
- });
-
- initSharedRunnersForm();
- initVariableList();
+initFilteredSearch({
+ page: FILTERED_SEARCH.ADMIN_RUNNERS,
+ filteredSearchTokenKeys: GroupRunnersFilteredSearchTokenKeys,
+ anchor: FILTERED_SEARCH.GROUP_RUNNERS_ANCHOR,
+ useDefaultState: false,
});
+
+initSharedRunnersForm();
+initVariableList();
+initInstallRunner();
diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
index d18cde4ac87..5d4c1595342 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -4,32 +4,32 @@ import registrySettingsApp from '~/registry/settings/registry_settings_bundle';
import initVariableList from '~/ci_variable_list';
import initDeployFreeze from '~/deploy_freeze';
import initSettingsPipelinesTriggers from '~/ci_settings_pipeline_triggers';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
-document.addEventListener('DOMContentLoaded', () => {
- // Initialize expandable settings panels
- initSettingsPanels();
+// Initialize expandable settings panels
+initSettingsPanels();
- const runnerToken = document.querySelector('.js-secret-runner-token');
- if (runnerToken) {
- const runnerTokenSecretValue = new SecretValues({
- container: runnerToken,
- });
- runnerTokenSecretValue.init();
- }
-
- initVariableList();
-
- // hide extra auto devops settings based checkbox state
- const autoDevOpsExtraSettings = document.querySelector('.js-extra-settings');
- const instanceDefaultBadge = document.querySelector('.js-instance-default-badge');
- document.querySelector('.js-toggle-extra-settings').addEventListener('click', event => {
- const { target } = event;
- if (instanceDefaultBadge) instanceDefaultBadge.style.display = 'none';
- autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked);
+const runnerToken = document.querySelector('.js-secret-runner-token');
+if (runnerToken) {
+ const runnerTokenSecretValue = new SecretValues({
+ container: runnerToken,
});
+ runnerTokenSecretValue.init();
+}
- registrySettingsApp();
- initDeployFreeze();
+initVariableList();
- initSettingsPipelinesTriggers();
+// hide extra auto devops settings based checkbox state
+const autoDevOpsExtraSettings = document.querySelector('.js-extra-settings');
+const instanceDefaultBadge = document.querySelector('.js-instance-default-badge');
+document.querySelector('.js-toggle-extra-settings').addEventListener('click', event => {
+ const { target } = event;
+ if (instanceDefaultBadge) instanceDefaultBadge.style.display = 'none';
+ autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked);
});
+
+registrySettingsApp();
+initDeployFreeze();
+
+initSettingsPipelinesTriggers();
+initInstallRunner();
diff --git a/app/assets/javascripts/pages/shared/mount_runner_instructions.js b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
new file mode 100644
index 00000000000..b7662155339
--- /dev/null
+++ b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import InstallRunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
+
+Vue.use(VueApollo);
+
+export function initInstallRunner(componentId = 'js-install-runner') {
+ const installRunnerEl = document.getElementById(componentId);
+ const { projectPath, groupPath } = installRunnerEl?.dataset;
+
+ if (installRunnerEl) {
+ const defaultClient = createDefaultClient();
+
+ const apolloProvider = new VueApollo({
+ defaultClient,
+ });
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: installRunnerEl,
+ apolloProvider,
+ provide: {
+ projectPath,
+ groupPath,
+ },
+ render(createElement) {
+ return createElement(InstallRunnerInstructions);
+ },
+ });
+ }
+}
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 7aee2573ce1..09f40601fbf 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -119,6 +119,9 @@ export default {
},
},
methods: {
+ hideTooltips() {
+ this.$root.$emit('bv::hide::tooltip');
+ },
pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete');
},
@@ -135,7 +138,7 @@ export default {
:class="jobClasses"
class="js-pipeline-graph-job-link qa-job-link menu-item"
data-testid="job-with-link"
- @click.stop
+ @click.stop="hideTooltips"
>
<job-name-component :name="job.name" :status="job.status" />
</gl-link>
diff --git a/app/assets/javascripts/static_site_editor/components/edit_area.vue b/app/assets/javascripts/static_site_editor/components/edit_area.vue
index 56f1a26f005..5b2d0207e98 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_area.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_area.vue
@@ -50,12 +50,12 @@ export default {
},
data() {
return {
- saveable: false,
parsedSource: parseSourceFile(this.preProcess(true, this.content)),
editorMode: EDITOR_TYPES.wysiwyg,
- isModified: false,
hasMatter: false,
isDrawerOpen: false,
+ isModified: false,
+ isSaveable: false,
};
},
imageRepository: imageRepository(),
@@ -85,8 +85,11 @@ export default {
return templatedContent;
},
refreshEditHelpers() {
- this.isModified = this.parsedSource.isModified();
- this.hasMatter = this.parsedSource.hasMatter();
+ const { isModified, hasMatter, isMatterValid } = this.parsedSource;
+ this.isModified = isModified();
+ this.hasMatter = hasMatter();
+ const hasValidMatter = this.hasMatter ? isMatterValid() : true;
+ this.isSaveable = this.isModified && hasValidMatter;
},
onDrawerOpen() {
this.isDrawerOpen = true;
@@ -142,12 +145,12 @@ export default {
@input="onInputChange"
@uploadImage="onUploadImage"
/>
- <unsaved-changes-confirm-dialog :modified="isModified" />
+ <unsaved-changes-confirm-dialog :modified="isSaveable" />
<publish-toolbar
class="gl-fixed gl-left-0 gl-bottom-0 gl-w-full"
:has-settings="hasSettings"
:return-url="returnUrl"
- :saveable="isModified"
+ :saveable="isSaveable"
:saving-changes="savingChanges"
@editSettings="onDrawerOpen"
@submit="onSubmit"
diff --git a/app/assets/javascripts/static_site_editor/services/front_matterify.js b/app/assets/javascripts/static_site_editor/services/front_matterify.js
index cbf0fffd515..60a5d799d11 100644
--- a/app/assets/javascripts/static_site_editor/services/front_matterify.js
+++ b/app/assets/javascripts/static_site_editor/services/front_matterify.js
@@ -16,6 +16,7 @@ export const frontMatterify = source => {
const NO_FRONTMATTER = {
source,
matter: null,
+ hasMatter: false,
spacing: null,
content: source,
delimiter: null,
@@ -53,6 +54,7 @@ export const frontMatterify = source => {
return {
source,
matter,
+ hasMatter: true,
spacing,
content,
delimiter,
diff --git a/app/assets/javascripts/static_site_editor/services/parse_source_file.js b/app/assets/javascripts/static_site_editor/services/parse_source_file.js
index d4fc8b2edb6..39126eb7bcc 100644
--- a/app/assets/javascripts/static_site_editor/services/parse_source_file.js
+++ b/app/assets/javascripts/static_site_editor/services/parse_source_file.js
@@ -1,15 +1,18 @@
import { frontMatterify, stringify } from './front_matterify';
const parseSourceFile = raw => {
- const remake = source => frontMatterify(source);
-
- let editable = remake(raw);
+ let editable;
const syncContent = (newVal, isBody) => {
if (isBody) {
editable.content = newVal;
} else {
- editable = remake(newVal);
+ try {
+ editable = frontMatterify(newVal);
+ editable.isMatterValid = true;
+ } catch (e) {
+ editable.isMatterValid = false;
+ }
}
};
@@ -23,10 +26,15 @@ const parseSourceFile = raw => {
const isModified = () => stringify(editable) !== raw;
- const hasMatter = () => Boolean(editable.matter);
+ const hasMatter = () => editable.hasMatter;
+
+ const isMatterValid = () => editable.isMatterValid;
+
+ syncContent(raw);
return {
matter,
+ isMatterValid,
syncMatter,
content,
syncContent,
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
new file mode 100644
index 00000000000..ff0626167a9
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
@@ -0,0 +1,20 @@
+query getRunnerPlatforms($projectPath: ID!, $groupPath: ID!) {
+ runnerPlatforms {
+ nodes {
+ name
+ humanReadableName
+ architectures {
+ nodes {
+ name
+ downloadLocation
+ }
+ }
+ }
+ }
+ project(fullPath: $projectPath) {
+ id
+ }
+ group(fullPath: $groupPath) {
+ id
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
new file mode 100644
index 00000000000..643c1991807
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
@@ -0,0 +1,16 @@
+query runnerSetupInstructions(
+ $platform: String!
+ $architecture: String!
+ $projectId: ID!
+ $groupId: ID!
+) {
+ runnerSetup(
+ platform: $platform
+ architecture: $architecture
+ projectId: $projectId
+ groupId: $groupId
+ ) {
+ installInstructions
+ registerInstructions
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
new file mode 100644
index 00000000000..995922454c4
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
@@ -0,0 +1,214 @@
+<script>
+import {
+ GlAlert,
+ GlButton,
+ GlModal,
+ GlModalDirective,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+} from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import getRunnerPlatforms from './graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructions from './graphql/queries/get_runner_setup.query.graphql';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlModal,
+ GlIcon,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ groupPath: {
+ default: '',
+ },
+ },
+ apollo: {
+ runnerPlatforms: {
+ query: getRunnerPlatforms,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ groupPath: this.groupPath,
+ };
+ },
+ update(data) {
+ return data;
+ },
+ error() {
+ this.showAlert = true;
+ },
+ },
+ },
+ data() {
+ return {
+ showAlert: false,
+ selectedPlatformArchitectures: [],
+ selectedPlatform: {},
+ selectedArchitecture: {},
+ runnerPlatforms: {},
+ instructions: {},
+ };
+ },
+ computed: {
+ isPlatformSelected() {
+ return Object.keys(this.selectedPlatform).length > 0;
+ },
+ instructionsEmpty() {
+ return this.instructions && Object.keys(this.instructions).length === 0;
+ },
+ groupId() {
+ return this.runnerPlatforms?.group?.id ?? '';
+ },
+ projectId() {
+ return this.runnerPlatforms?.project?.id ?? '';
+ },
+ platforms() {
+ return this.runnerPlatforms.runnerPlatforms?.nodes;
+ },
+ },
+ methods: {
+ selectPlatform(name) {
+ this.selectedPlatform = this.platforms.find(platform => platform.name === name);
+ this.selectedPlatformArchitectures = this.selectedPlatform?.architectures?.nodes;
+ [this.selectedArchitecture] = this.selectedPlatformArchitectures;
+ this.selectArchitecture(this.selectedArchitecture);
+ },
+ selectArchitecture(architecture) {
+ this.selectedArchitecture = architecture;
+
+ this.$apollo.addSmartQuery('instructions', {
+ variables() {
+ return {
+ platform: this.selectedPlatform.name,
+ architecture: this.selectedArchitecture.name,
+ projectId: this.projectId,
+ groupId: this.groupId,
+ };
+ },
+ query: getRunnerSetupInstructions,
+ update(data) {
+ return data?.runnerSetup;
+ },
+ error() {
+ this.showAlert = true;
+ },
+ });
+ },
+ toggleAlert(state) {
+ this.showAlert = state;
+ },
+ },
+ modalId: 'installation-instructions-modal',
+ i18n: {
+ installARunner: __('Install a Runner'),
+ architecture: s__('Runners|Architecture'),
+ downloadInstallBinary: s__('Runners|Download and Install Binary'),
+ downloadLatestBinary: s__('Runners|Download Latest Binary'),
+ registerRunner: s__('Runners|Register Runner'),
+ method: __('Method'),
+ fetchError: s__('An error has occurred fetching instructions'),
+ instructions: __('Show Runner installation instructions'),
+ },
+ closeButton: {
+ text: __('Close'),
+ attributes: [{ variant: 'default' }],
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-button v-gl-modal-directive="$options.modalId" data-testid="show-modal-button">
+ {{ $options.i18n.instructions }}
+ </gl-button>
+ <gl-modal
+ :modal-id="$options.modalId"
+ :title="$options.i18n.installARunner"
+ :action-secondary="$options.closeButton"
+ >
+ <gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)">
+ {{ $options.i18n.fetchError }}
+ </gl-alert>
+ <h5>{{ __('Environment') }}</h5>
+ <gl-button-group class="gl-mb-5">
+ <gl-button
+ v-for="platform in platforms"
+ :key="platform.name"
+ data-testid="platform-button"
+ @click="selectPlatform(platform.name)"
+ >
+ {{ platform.humanReadableName }}
+ </gl-button>
+ </gl-button-group>
+ <template v-if="isPlatformSelected">
+ <h5>
+ {{ $options.i18n.architecture }}
+ </h5>
+ <gl-dropdown class="gl-mb-5" :text="selectedArchitecture.name">
+ <gl-dropdown-item
+ v-for="architecture in selectedPlatformArchitectures"
+ :key="architecture.name"
+ data-testid="architecture-dropdown-item"
+ @click="selectArchitecture(architecture)"
+ >
+ {{ architecture.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ <div class="gl-display-flex gl-align-items-center gl-mb-5">
+ <h5>{{ $options.i18n.downloadInstallBinary }}</h5>
+ <gl-button
+ class="gl-ml-auto"
+ :href="selectedArchitecture.downloadLocation"
+ download
+ data-testid="binary-download-button"
+ >
+ {{ $options.i18n.downloadLatestBinary }}
+ </gl-button>
+ </div>
+ </template>
+ <template v-if="!instructionsEmpty">
+ <div class="gl-display-flex">
+ <pre class="bg-light gl-flex-fill-1" data-testid="binary-instructions">
+ {{ instructions.installInstructions }}
+ </pre>
+ <gl-button
+ class="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ variant="link"
+ :data-clipboard-text="instructions.installationInstructions"
+ >
+ <gl-icon name="copy-to-clipboard" />
+ </gl-button>
+ </div>
+
+ <hr />
+ <h5 class="gl-mb-5">{{ $options.i18n.registerRunner }}</h5>
+ <h5 class="gl-mb-5">{{ $options.i18n.method }}</h5>
+ <div class="gl-display-flex">
+ <pre class="bg-light gl-flex-fill-1" data-testid="runner-instructions">
+ {{ instructions.registerInstructions }}
+ </pre>
+ <gl-button
+ class="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ variant="link"
+ :data-clipboard-text="instructions.registerInstructions"
+ >
+ <gl-icon name="copy-to-clipboard" />
+ </gl-button>
+ </div>
+ </template>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/stylesheets/pages/incident_management_list.scss b/app/assets/stylesheets/pages/incident_management_list.scss
index c0a1fa72b1f..9ba79dd1235 100644
--- a/app/assets/stylesheets/pages/incident_management_list.scss
+++ b/app/assets/stylesheets/pages/incident_management_list.scss
@@ -8,13 +8,12 @@
@include gl-text-gray-500;
tbody {
- tr:not(.b-table-busy-slot) {
- // TODO replace with gitlab/ui utilities: https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1791
+ tr:not(.b-table-busy-slot):not(.b-table-empty-row) {
&:hover {
- border-top-style: double;
+ @include gl-border-t-double;
td {
- border-bottom-style: initial;
+ @include gl-border-b-initial;
}
}
}
@@ -22,7 +21,7 @@
tr {
&:focus {
- outline: none;
+ @include gl-outline-none;
}
td,
@@ -118,22 +117,22 @@
}
.gl-tabs-nav {
- border-bottom-width: 0;
+ @include gl-border-b-0;
.gl-tab-nav-item {
- color: $gray-500;
+ @include gl-text-gray-500;
> .gl-tab-counter-badge {
- color: inherit;
+ @include gl-reset-color;
@include gl-font-sm;
- background-color: $gray-50;
+ @include gl-bg-gray-50;
}
}
}
@include media-breakpoint-down(xs) {
.list-header {
- flex-direction: column-reverse;
+ @include gl-flex-direction-column-reverse;
}
.create-incident-button {
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index c85c83688a4..afebeafff7c 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -127,7 +127,7 @@ class ProfilesController < Profiles::ApplicationController
:include_private_contributions,
:timezone,
:job_title,
- status: [:emoji, :message]
+ status: [:emoji, :message, :availability]
)
end
end
diff --git a/app/graphql/types/availability_enum.rb b/app/graphql/types/availability_enum.rb
new file mode 100644
index 00000000000..61686b9359f
--- /dev/null
+++ b/app/graphql/types/availability_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class AvailabilityEnum < BaseEnum
+ graphql_name 'AvailabilityEnum'
+ description 'User availability status'
+
+ ::UserStatus.availabilities.keys.each do |availability_value|
+ value availability_value.upcase, value: availability_value, description: availability_value.titleize
+ end
+ end
+end
diff --git a/app/graphql/types/terraform/state_type.rb b/app/graphql/types/terraform/state_type.rb
index 3ee7361baf1..05b6d130f19 100644
--- a/app/graphql/types/terraform/state_type.rb
+++ b/app/graphql/types/terraform/state_type.rb
@@ -27,6 +27,11 @@ module Types
null: true,
description: 'Timestamp the Terraform state was locked'
+ field :latest_version, Types::Terraform::StateVersionType,
+ complexity: 3,
+ null: true,
+ description: 'The latest version of the Terraform state'
+
field :created_at, Types::TimeType,
null: false,
description: 'Timestamp the Terraform state was created'
diff --git a/app/graphql/types/terraform/state_version_type.rb b/app/graphql/types/terraform/state_version_type.rb
new file mode 100644
index 00000000000..7a5663c6324
--- /dev/null
+++ b/app/graphql/types/terraform/state_version_type.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Types
+ module Terraform
+ class StateVersionType < BaseObject
+ graphql_name 'TerraformStateVersion'
+
+ authorize :read_terraform_state
+
+ field :id, GraphQL::ID_TYPE,
+ null: false,
+ description: 'ID of the Terraform state version'
+
+ field :created_by_user, Types::UserType,
+ null: true,
+ authorize: :read_user,
+ description: 'The user that created this version',
+ resolve: -> (version, _, _) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, version.created_by_user_id).find }
+
+ field :created_at, Types::TimeType,
+ null: false,
+ description: 'Timestamp the version was created'
+
+ field :updated_at, Types::TimeType,
+ null: false,
+ description: 'Timestamp the version was updated'
+ end
+ end
+end
diff --git a/app/graphql/types/user_status_type.rb b/app/graphql/types/user_status_type.rb
index ff277c1f8e8..9cf6c862d3d 100644
--- a/app/graphql/types/user_status_type.rb
+++ b/app/graphql/types/user_status_type.rb
@@ -11,5 +11,7 @@ module Types
description: 'User status message'
field :emoji, GraphQL::STRING_TYPE, null: true,
description: 'String representation of emoji'
+ field :availability, Types::AvailabilityEnum, null: false,
+ description: 'User availability status'
end
end
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index 9965a705a01..7234cbb29cc 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -29,7 +29,8 @@ module OperationsHelper
'url' => alerts_service.url,
'alerts_setup_url' => help_page_path('operations/incident_management/alert_integrations.md', anchor: 'generic-http-endpoint'),
'alerts_usage_url' => project_alert_management_index_path(@project),
- 'disabled' => disabled.to_s
+ 'disabled' => disabled.to_s,
+ 'project_path' => project_path(@project)
}
end
diff --git a/app/models/deployment_merge_request.rb b/app/models/deployment_merge_request.rb
index b67f96906f5..64a578e16bf 100644
--- a/app/models/deployment_merge_request.rb
+++ b/app/models/deployment_merge_request.rb
@@ -14,7 +14,12 @@ class DeploymentMergeRequest < ApplicationRecord
end
def self.deployed_to(name)
+ # We filter by project ID again so the query uses the index on
+ # (project_id, name), instead of using the index on
+ # (name varchar_pattern_ops). This results in better performance on
+ # GitLab.com.
where('environments.name = ?', name)
+ .where('environments.project_id = merge_requests.target_project_id')
end
def self.deployed_after(time)
diff --git a/app/models/terraform/state.rb b/app/models/terraform/state.rb
index c0579c7eedc..d329b429c9d 100644
--- a/app/models/terraform/state.rb
+++ b/app/models/terraform/state.rb
@@ -17,8 +17,15 @@ module Terraform
belongs_to :project
belongs_to :locked_by_user, class_name: 'User'
- has_many :versions, class_name: 'Terraform::StateVersion', foreign_key: :terraform_state_id
- has_one :latest_version, -> { ordered_by_version_desc }, class_name: 'Terraform::StateVersion', foreign_key: :terraform_state_id
+ has_many :versions,
+ class_name: 'Terraform::StateVersion',
+ foreign_key: :terraform_state_id,
+ inverse_of: :terraform_state
+
+ has_one :latest_version, -> { ordered_by_version_desc },
+ class_name: 'Terraform::StateVersion',
+ foreign_key: :terraform_state_id,
+ inverse_of: :terraform_state
scope :versioning_not_enabled, -> { where(versioning_enabled: false) }
scope :ordered_by_name, -> { order(:name) }
diff --git a/app/models/user_status.rb b/app/models/user_status.rb
index 016b89bae81..0e1ae0b7338 100644
--- a/app/models/user_status.rb
+++ b/app/models/user_status.rb
@@ -9,6 +9,8 @@ class UserStatus < ApplicationRecord
belongs_to :user
+ enum availability: { not_set: 0, busy: 1 }
+
validates :user, presence: true
validates :emoji, inclusion: { in: Gitlab::Emoji.emojis_names }
validates :message, length: { maximum: 100 }, allow_blank: true
diff --git a/app/policies/terraform/state_version_policy.rb b/app/policies/terraform/state_version_policy.rb
new file mode 100644
index 00000000000..ad0b2f6d594
--- /dev/null
+++ b/app/policies/terraform/state_version_policy.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Terraform
+ class StateVersionPolicy < BasePolicy
+ alias_method :terraform_state_version, :subject
+
+ delegate { terraform_state_version.terraform_state }
+ end
+end
diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb
index d6e5b825e13..525f8a25d04 100644
--- a/app/services/projects/lfs_pointers/lfs_download_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_service.rb
@@ -22,7 +22,7 @@ module Projects
def execute
return unless project&.lfs_enabled? && lfs_download_object
return error("LFS file with oid #{lfs_oid} has invalid attributes") unless lfs_download_object.valid?
- return link_existing_lfs_object! if Feature.enabled?(:lfs_link_existing_object, project, default_enabled: true) && lfs_size > LARGE_FILE_SIZE && lfs_object
+ return link_existing_lfs_object! if lfs_size > LARGE_FILE_SIZE && lfs_object
wrap_download_errors do
download_lfs_file!
diff --git a/app/services/users/set_status_service.rb b/app/services/users/set_status_service.rb
index 89008368d5f..356c8782af1 100644
--- a/app/services/users/set_status_service.rb
+++ b/app/services/users/set_status_service.rb
@@ -14,7 +14,7 @@ module Users
def execute
return false unless can?(current_user, :update_user_status, target_user)
- if params[:emoji].present? || params[:message].present?
+ if params[:emoji].present? || params[:message].present? || params[:availability].present?
set_status
else
remove_status
@@ -25,6 +25,9 @@ module Users
def set_status
params[:emoji] = UserStatus::DEFAULT_EMOJI if params[:emoji].blank?
+ params.delete(:availability) if params[:availability].blank?
+ return false if params[:availability].present? && UserStatus.availabilities.keys.exclude?(params[:availability])
+
user_status.update(params)
end
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index 3d3b8c28a17..c2d7b63f1f9 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -39,7 +39,9 @@
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token,
type: 'shared',
- reset_token_url: reset_registration_token_admin_application_settings_path }
+ reset_token_url: reset_registration_token_admin_application_settings_path,
+ project_path: '',
+ group_path: '' }
.row
.col-sm-9
diff --git a/app/views/ci/runner/_how_to_setup_runner.html.haml b/app/views/ci/runner/_how_to_setup_runner.html.haml
index 4ea3b0f0fb9..0ff6fdc6354 100644
--- a/app/views/ci/runner/_how_to_setup_runner.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner.html.haml
@@ -19,3 +19,5 @@
data: { confirm: _("Are you sure you want to reset registration token?") }
%li
= _("Start the Runner!")
+
+#js-install-runner{ data: { project_path: project_path, group_path: group_path } }
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index 554240b7aef..087c38c7b86 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -17,4 +17,6 @@
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @group.runners_token,
type: 'group',
- reset_token_url: reset_registration_token_group_settings_ci_cd_path }
+ reset_token_url: reset_registration_token_group_settings_ci_cd_path,
+ project_path: '',
+ group_path: @group.path }
diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml
index 4cc67a8f5d8..d7fe141e802 100644
--- a/app/views/projects/runners/_specific_runners.html.haml
+++ b/app/views/projects/runners/_specific_runners.html.haml
@@ -9,7 +9,9 @@
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @project.runners_token,
type: 'specific',
- reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path }
+ reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path,
+ project_path: @project.path_with_namespace,
+ group_path: '' }
- if @project_runners.any?
%h4.underlined-title= _('Runners activated for this project')
diff --git a/bin/background_jobs b/bin/background_jobs
index 866f5c39cd6..cbc501094c4 100755
--- a/bin/background_jobs
+++ b/bin/background_jobs
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-cd $(dirname $0)/..
+cd $(dirname $0)/.. || exit 1
if [ -n "$SIDEKIQ_WORKERS" ] ; then
exec bin/background_jobs_sk_cluster "$@"
diff --git a/bin/mail_room b/bin/mail_room
index be608be4229..cf9d422909e 100755
--- a/bin/mail_room
+++ b/bin/mail_room
@@ -1,6 +1,6 @@
#!/bin/sh
-cd $(dirname $0)/..
+cd $(dirname $0)/.. || exit 1
app_root=$(pwd)
mail_room_pidfile="$app_root/tmp/pids/mail_room.pid"
diff --git a/bin/web_unicorn b/bin/web_unicorn
index 41e2ac44351..5fa15a8324b 100755
--- a/bin/web_unicorn
+++ b/bin/web_unicorn
@@ -1,6 +1,6 @@
#!/bin/sh
-cd $(dirname $0)/..
+cd $(dirname $0)/.. || exit 1
app_root=$(pwd)
unicorn_pidfile="$app_root/tmp/pids/unicorn.pid"
diff --git a/changelogs/unreleased/267147-terraform-state-versions-graphql.yml b/changelogs/unreleased/267147-terraform-state-versions-graphql.yml
new file mode 100644
index 00000000000..0eb03990dd1
--- /dev/null
+++ b/changelogs/unreleased/267147-terraform-state-versions-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add latest version field to Terraform state GraphQL type
+merge_request: 45848
+author:
+type: added
diff --git a/changelogs/unreleased/271550-fj-forbid-realtime_changes-in-robots.yml b/changelogs/unreleased/271550-fj-forbid-realtime_changes-in-robots.yml
new file mode 100644
index 00000000000..b90a85fa043
--- /dev/null
+++ b/changelogs/unreleased/271550-fj-forbid-realtime_changes-in-robots.yml
@@ -0,0 +1,5 @@
+---
+title: Disallow realtime_changes route in robots.txt
+merge_request: 45986
+author:
+type: changed
diff --git a/changelogs/unreleased/ImproveShellScriptsChangeDirException.yml b/changelogs/unreleased/ImproveShellScriptsChangeDirException.yml
new file mode 100644
index 00000000000..8d14907e88d
--- /dev/null
+++ b/changelogs/unreleased/ImproveShellScriptsChangeDirException.yml
@@ -0,0 +1,5 @@
+---
+title: Execute `exit 1` when shell script `cd` fails
+merge_request: 46122
+author: Peter Dave Hello
+type: other
diff --git a/changelogs/unreleased/feature-flags-edit-increase-loading-icon-size.yml b/changelogs/unreleased/feature-flags-edit-increase-loading-icon-size.yml
new file mode 100644
index 00000000000..89b3fe093ba
--- /dev/null
+++ b/changelogs/unreleased/feature-flags-edit-increase-loading-icon-size.yml
@@ -0,0 +1,5 @@
+---
+title: Make loading icon on feature flag edit page larger
+merge_request: 46268
+author:
+type: fixed
diff --git a/changelogs/unreleased/jivanvl-runner-guided-install-frontend.yml b/changelogs/unreleased/jivanvl-runner-guided-install-frontend.yml
new file mode 100644
index 00000000000..d103c4015d4
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-runner-guided-install-frontend.yml
@@ -0,0 +1,5 @@
+---
+title: Add install GitLab runner popup
+merge_request: 42877
+author:
+type: added
diff --git a/changelogs/unreleased/job-dropdown-click.yml b/changelogs/unreleased/job-dropdown-click.yml
new file mode 100644
index 00000000000..14e44273d5e
--- /dev/null
+++ b/changelogs/unreleased/job-dropdown-click.yml
@@ -0,0 +1,5 @@
+---
+title: 'Job dropdown: Hide tooltip explicitly on click'
+merge_request: 46465
+author:
+type: fixed
diff --git a/changelogs/unreleased/set-user-availability-be.yml b/changelogs/unreleased/set-user-availability-be.yml
new file mode 100644
index 00000000000..39b821831c6
--- /dev/null
+++ b/changelogs/unreleased/set-user-availability-be.yml
@@ -0,0 +1,5 @@
+---
+title: Add availability to user status
+merge_request: 45888
+author:
+type: added
diff --git a/config/feature_flags/development/lfs_link_existing_object.yml b/config/feature_flags/development/lfs_link_existing_object.yml
deleted file mode 100644
index f38bb4525ec..00000000000
--- a/config/feature_flags/development/lfs_link_existing_object.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: lfs_link_existing_object
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41770
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249246
-group: group::source code
-type: development
-default_enabled: true
diff --git a/db/migrate/20201022103304_add_availability_to_user_statuses.rb b/db/migrate/20201022103304_add_availability_to_user_statuses.rb
new file mode 100644
index 00000000000..9144c81fcfb
--- /dev/null
+++ b/db/migrate/20201022103304_add_availability_to_user_statuses.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddAvailabilityToUserStatuses < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :user_statuses, :availability, :integer, limit: 2, default: 0, null: false
+ end
+end
diff --git a/db/schema_migrations/20201022103304 b/db/schema_migrations/20201022103304
new file mode 100644
index 00000000000..e54cb431bd4
--- /dev/null
+++ b/db/schema_migrations/20201022103304
@@ -0,0 +1 @@
+aa15aad0b51f313f3cd59e1065023146fe53c6bd50319656ae992f8f43e1525e \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index b799ff61d74..15bcb7f7632 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -16782,7 +16782,8 @@ CREATE TABLE user_statuses (
cached_markdown_version integer,
emoji character varying DEFAULT 'speech_balloon'::character varying NOT NULL,
message character varying(100),
- message_html character varying
+ message_html character varying,
+ availability smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE user_statuses_user_id_seq
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index 53690138300..4a6cb4ee479 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -95,6 +95,7 @@ exceptions:
- URI
- URL
- USB
+ - UTC
- UUID
- VPC
- WIP
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 5ea53511458..10e5eb8cc61 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -116,6 +116,7 @@ The following are required to run Geo:
- [Ubuntu](https://ubuntu.com) 16.04+
- PostgreSQL 11+ with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
- Git 2.9+
+- Git-lfs 2.4.2+ on the user side when using LFS
- All nodes must run the same GitLab version.
Additionally, check GitLab's [minimum requirements](../../install/requirements.md),
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index b62c5c6f460..e60b9567c6f 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -782,3 +782,13 @@ To resolve this issue:
using IPv6 to send its status to the **primary** node. If it is, add an entry to
the **primary** node using IPv4 in the `/etc/hosts` file. Alternatively, you should
[enable IPv6 on the **primary** node](https://docs.gitlab.com/omnibus/settings/nginx.html#setting-the-nginx-listen-address-or-addresses).
+
+## Fixing client errors
+
+### Authorization errors from LFS HTTP(s) client requests
+
+You may have problems if you're running a version of [Git LFS](https://git-lfs.github.com/) before 2.4.2.
+As noted in [this authentication issue](https://github.com/git-lfs/git-lfs/issues/3025),
+requests redirected from the secondary to the primary node do not properly send the
+Authorization header. This may result in either an infinite `Authorization <-> Redirect`
+loop, or Authorization errors.
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index 7074b696796..b311bee1a5b 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -12,15 +12,19 @@ another file system or another server.
## Moving data within a GitLab instance
-The recommended way to move Git repositories between servers, between different storage, and
-from unclustered to clustered Gitaly (Praefect) is using the API.
+The GitLab API is the recommended way to move Git repositories:
-Read more:
+- Between servers.
+- Between different storage.
+- From single-node Gitaly to Gitaly Cluster.
-- [Configuring additional storage for Gitaly](../gitaly/index.md#network-architecture)
- - Within this example, additional storage called `storage1` and `storage2` is configured.
-- [The API documentation](../../api/project_repository_storage_moves.md) details the endpoints for quering and scheduling repository moves.
-- [Migrate existing repositories to Gitaly Cluster](../gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster)
+For more information, see:
+
+- [Configuring additional storage for Gitaly](../gitaly/index.md#network-architecture). Within this
+ example, additional storage called `storage1` and `storage2` is configured.
+- [The API documentation](../../api/project_repository_storage_moves.md) details the endpoints for
+ querying and scheduling repository moves.
+- [Migrate existing repositories to Gitaly Cluster](../gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
### Limitations
@@ -28,12 +32,13 @@ Read more in the [API documentation](../../api/project_repository_storage_moves.
## Migrating to another GitLab instance
-Using the API isn't an option if you are migrating to a new GitLab environment, for example:
+[Using the API](#moving-data-within-a-gitlab-instance) isn't an option if you are migrating to a new
+GitLab environment, for example:
- From a single-node GitLab to a scaled-out architecture.
- From a GitLab instance in your private datacenter to a cloud provider.
-The rest of the document will look
+The rest of the document looks
at some of the ways you can copy all your repositories from
`/var/opt/gitlab/git-data/repositories` to `/mnt/gitlab/repositories`.
@@ -49,10 +54,14 @@ Each of the approaches we list can or does overwrite data in the target director
### Recommended approach in all cases
-GitLab's [backup and restore capability](../../raketasks/backup_restore.md) should be used. Git repositories are accessed, managed and stored on GitLab servers by the Gitaly component of the product as a database. Data loss can result from directly accessing and copying Gitaly's files using tools like `rsync`.
+GitLab's [backup and restore capability](../../raketasks/backup_restore.md) should be used. Git
+repositories are accessed, managed, and stored on GitLab servers by Gitaly as a database. Data loss
+can result from directly accessing and copying Gitaly's files using tools like `rsync`.
-- From GitLab 13.3, backup performance can be improved by [processing multiple repositories concurrently](../../raketasks/backup_restore.md#back-up-git-repositories-concurrently).
-- Backups can be created of just the repositories using the [skip feature](../../raketasks/backup_restore.md#excluding-specific-directories-from-the-backup)
+- From GitLab 13.3, backup performance can be improved by
+ [processing multiple repositories concurrently](../../raketasks/backup_restore.md#back-up-git-repositories-concurrently).
+- Backups can be created of just the repositories using the
+ [skip feature](../../raketasks/backup_restore.md#excluding-specific-directories-from-the-backup).
### Target directory is empty: use a `tar` pipe
@@ -86,8 +95,7 @@ If you want to compress the data before it goes over the network
### The target directory contains an outdated copy of the repositories: use `rsync`
DANGER: **Warning:**
-Using `rsync` to migrate
-Git data can cause data loss and repository corruption.
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
If the target directory already contains a partial / outdated copy
@@ -108,8 +116,7 @@ If you want to see progress, replace `-a` with `-av`.
#### Single `rsync` to another server
DANGER: **Warning:**
-Using `rsync` to migrate
-Git data can cause data loss and repository corruption.
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
If the `git` user on your source system has SSH access to the target
@@ -123,8 +130,7 @@ sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
### Thousands of Git repositories: use one `rsync` per repository
DANGER: **Warning:**
-Using `rsync` to migrate
-Git data can cause data loss and repository corruption.
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
Every time you start an `rsync` job it has to inspect all files in
@@ -145,8 +151,7 @@ longer exist at the source.**
#### Parallel `rsync` for all repositories known to GitLab
DANGER: **Warning:**
-Using `rsync` to migrate
-Git data can cause data loss and repository corruption.
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
This syncs repositories with 10 `rsync` processes at a time. We keep
@@ -207,8 +212,7 @@ cat /home/git/transfer-logs/* | sort | uniq -u |\
#### Parallel `rsync` only for repositories with recent activity
DANGER: **Warning:**
-Using `rsync` to migrate
-Git data can cause data loss and repository corruption.
+Using `rsync` to migrate Git data can cause data loss and repository corruption.
[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
Suppose you have already done one sync that started after 2015-10-1 12:00 UTC.
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 3999f982a36..fd7890700f4 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -928,6 +928,21 @@ type AlertTodoCreatePayload {
}
"""
+User availability status
+"""
+enum AvailabilityEnum {
+ """
+ Busy
+ """
+ BUSY
+
+ """
+ Not Set
+ """
+ NOT_SET
+}
+
+"""
An emoji awarded by a user
"""
type AwardEmoji {
@@ -19320,6 +19335,11 @@ type TerraformState {
id: ID!
"""
+ The latest version of the Terraform state
+ """
+ latestVersion: TerraformStateVersion
+
+ """
Timestamp the Terraform state was locked
"""
lockedAt: Time
@@ -19475,6 +19495,28 @@ type TerraformStateUnlockPayload {
errors: [String!]!
}
+type TerraformStateVersion {
+ """
+ Timestamp the version was created
+ """
+ createdAt: Time!
+
+ """
+ The user that created this version
+ """
+ createdByUser: User
+
+ """
+ ID of the Terraform state version
+ """
+ id: ID!
+
+ """
+ Timestamp the version was updated
+ """
+ updatedAt: Time!
+}
+
"""
Represents the Geo sync and verification state of a terraform state version
"""
@@ -21451,6 +21493,11 @@ enum UserState {
type UserStatus {
"""
+ User availability status
+ """
+ availability: AvailabilityEnum!
+
+ """
String representation of emoji
"""
emoji: String
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 0b4f3652cc8..0d723445d75 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -2392,6 +2392,29 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "AvailabilityEnum",
+ "description": "User availability status",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "NOT_SET",
+ "description": "Not Set",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "BUSY",
+ "description": "Busy",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "AwardEmoji",
"description": "An emoji awarded by a user",
@@ -56012,6 +56035,20 @@
"deprecationReason": null
},
{
+ "name": "latestVersion",
+ "description": "The latest version of the Terraform state",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TerraformStateVersion",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "lockedAt",
"description": "Timestamp the Terraform state was locked",
"args": [
@@ -56489,6 +56526,87 @@
},
{
"kind": "OBJECT",
+ "name": "TerraformStateVersion",
+ "description": null,
+ "fields": [
+ {
+ "name": "createdAt",
+ "description": "Timestamp the version was created",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdByUser",
+ "description": "The user that created this version",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the Terraform state version",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updatedAt",
+ "description": "Timestamp the version was updated",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "TerraformStateVersionRegistry",
"description": "Represents the Geo sync and verification state of a terraform state version",
"fields": [
@@ -62029,6 +62147,24 @@
"description": null,
"fields": [
{
+ "name": "availability",
+ "description": "User availability status",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "AvailabilityEnum",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "emoji",
"description": "String representation of emoji",
"args": [
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 5e960f293bd..2e88624a550 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -2683,6 +2683,7 @@ Completion status of tasks.
| ----- | ---- | ----------- |
| `createdAt` | Time! | Timestamp the Terraform state was created |
| `id` | ID! | ID of the Terraform state |
+| `latestVersion` | TerraformStateVersion | The latest version of the Terraform state |
| `lockedAt` | Time | Timestamp the Terraform state was locked |
| `lockedByUser` | User | The user currently holding a lock on the Terraform state |
| `name` | String! | Name of the Terraform state |
@@ -2715,6 +2716,15 @@ Autogenerated return type of TerraformStateUnlock.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+### TerraformStateVersion
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | Time! | Timestamp the version was created |
+| `createdByUser` | User | The user that created this version |
+| `id` | ID! | ID of the Terraform state version |
+| `updatedAt` | Time! | Timestamp the version was updated |
+
### TerraformStateVersionRegistry
Represents the Geo sync and verification state of a terraform state version.
@@ -2990,6 +3000,7 @@ Autogenerated return type of UpdateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `availability` | AvailabilityEnum! | User availability status |
| `emoji` | String | String representation of emoji |
| `message` | String | User status message |
| `messageHtml` | String | HTML of the user status message |
@@ -3318,6 +3329,15 @@ Alert status values.
| `RESOLVED` | Resolved status |
| `TRIGGERED` | Triggered status |
+### AvailabilityEnum
+
+User availability status.
+
+| Value | Description |
+| ----- | ----------- |
+| `BUSY` | Busy |
+| `NOT_SET` | Not Set |
+
### BlobViewersType
Types of blob viewers.
diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md
index d9be616e4c1..50683a7b815 100644
--- a/doc/api/project_repository_storage_moves.md
+++ b/doc/api/project_repository_storage_moves.md
@@ -32,8 +32,8 @@ This API requires you to [authenticate yourself](README.md#authentication) as an
## Limitations
-- [The repositories associated with snippets can't currently be moved with the API](https://gitlab.com/groups/gitlab-org/-/epics/3393).
-- [Group level wikis can't currently be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
+- The repositories associated with snippets [can't be moved with the API](https://gitlab.com/groups/gitlab-org/-/epics/3393).
+- Group-level wikis [can't be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
## Retrieve all project repository storage moves
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
index 45cae49377f..86c66b5ea2d 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
@@ -208,8 +208,8 @@ ask an administrator to execute the following commands:
```shell
> sudo gitlab-rails console # Login to Rails console of GitLab instance.
> Feature.enabled?(:disable_merge_trains) # Check if it's disabled or not.
-> Feature.enable(:disable_merge_trains) # Disable Merge Trains.
-> Feature.disable(:disable_merge_trains) # Enable Merge Trains.
+> Feature.enable(:disable_merge_trains) # Enable Merge Trains.
+> Feature.disable(:disable_merge_trains) # Disable Merge Trains.
```
When you disable this feature, all existing merge trains are cancelled and
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index f397b03fe37..0e463735566 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -6,7 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Incidents
-Incidents are critical entities in incident management workflows. They represent a service disruption or outage that needs to be restored urgently. GitLab provides tools for the triage, response, and remediation of incidents.
+Incidents are critical entities in incident management workflows. They represent
+a service disruption or outage that needs to be restored urgently. GitLab provides
+tools for the triage, response, and remediation of incidents.
## Incident Creation
@@ -14,7 +16,8 @@ You can create an incident manually or automatically.
### Create incidents manually
-If you have at least Guest [permissions](../../user/permissions.md), to create an Incident, you have two options to do this manually.
+If you have at least Guest [permissions](../../user/permissions.md), to create an
+Incident, you have two options to do this manually.
**From the Incidents List:**
@@ -43,17 +46,17 @@ If you have at least Guest [permissions](../../user/permissions.md), to create a
With Maintainer or higher [permissions](../../user/permissions.md), you can enable
GitLab to create incident automatically whenever an alert is triggered:
-1. Navigate to **Settings > Operations > Incidents** and expand
- **Incidents**:
+1. Navigate to **Settings > Operations > Incidents** and expand **Incidents**:
![Incident Management Settings](./img/incident_management_settings_v13_3.png)
-1. Check the **Create an incident**
- checkbox.
-1. To customize the incident, select an [issue templates](../../user/project/description_templates.md#creating-issue-templates).
+1. Check the **Create an incident** checkbox.
+1. To customize the incident, select an
+ [issue template](../../user/project/description_templates.md#creating-issue-templates).
1. To send [an email notification](alert_notifications.md#email-notifications) to users
with [Developer permissions](../../user/permissions.md), select
- **Send a separate email notification to Developers**. Email notifications will also be sent to users with **Maintainer** and **Owner** permissions.
+ **Send a separate email notification to Developers**. Email notifications are
+ also sent to users with **Maintainer** and **Owner** permissions.
1. Click **Save changes**.
### Create incidents via the PagerDuty webhook
@@ -183,10 +186,22 @@ un-threaded and ordered chronologically, newest to oldest:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241663) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
-After enabling **Incident SLA** in the Incident Management configuration, newly-created
-incidents display a SLA (Service Level Agreement) timer showing the time remaining before
-the SLA period expires. If the incident is not closed before the SLA period ends, GitLab
-adds a `missed::SLA` label to the incident.
+You can enable the Service Level Agreement Countdown timer on incidents to track
+the Service Level Agreements (SLAs) you hold with your customers. The timer is
+automatically started when the incident is created, and shows the time
+remaining before the SLA period expires. To configure the timer:
+
+1. Navigate to **Settings > Operations**.
+1. Scroll to **Incidents** and click **Expand**, then select the
+ **Incident settings** tab.
+1. Select **Activate "time to SLA" countdown timer**.
+1. Set a time limit in increments of 15 minutes.
+1. Click **Save changes**.
+
+After you enable the SLA countdown timer, the **Time to SLA** attribute is displayed
+as a column in the Incidents List, and as a field on newly created Incidents. If
+the incident isn't closed before the SLA period ends, GitLab adds a `missed::SLA`
+label to the incident.
## Incident Actions
@@ -194,15 +209,18 @@ There are different actions available to help triage and respond to incidents.
### Assign incidents
-Assign incidents to users that are actively responding. Select **Edit** in the right-hand side bar to select or deselect assignees.
+Assign incidents to users that are actively responding. Select **Edit** in the
+right-hand side bar to select or deselect assignees.
### Change severity
-See [Incident List](#incident-list) for a full description of the severities available. Select **Edit** in the right-hand side bar to change the severity of an incident.
+See [Incident List](#incident-list) for a full description of the severity levels available.
+Select **Edit** in the right-hand side bar to change the severity of an incident.
### Add a to-do item
-Add a to-do for incidents that you want to track in your to-do list. Click the **Add a to do** button at the top of the right-hand side bar to add a to-do item.
+Add a to-do for incidents that you want to track in your to-do list. Click the
+**Add a to do** button at the top of the right-hand side bar to add a to-do item.
### Manage incidents from Slack
diff --git a/doc/update/README.md b/doc/update/README.md
index b5e99671278..901e187d2f5 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -263,9 +263,9 @@ with the older Rails version - which could cause non-GET requests to
fail for [multi-node GitLab installations](https://docs.gitlab.com/omnibus/update/#multi-node--ha-deployment).
So, if you are using multiple Rails servers and specifically upgrading from 13.0,
-all servers must first be upgraded to 13.1.0 before upgrading to later versions:
+all servers must first be upgraded to 13.1.X before upgrading to 13.2.0 or later:
-1. Ensure all GitLab web nodes are on GitLab 13.1.0.
+1. Ensure all GitLab web nodes are on GitLab 13.1.X.
1. Optionally, enable the `global_csrf_token` feature flag to enable new
method of CSRF token generation:
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 2c838724cb3..35e6f3b4136 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -414,8 +414,13 @@ There are a few limitations compared to project wikis:
- Local Git access is not supported yet.
- Group wikis are not included in global search, group exports, backups, and Geo replication.
- Changes to group wikis don't show up in the group's activity feed.
+- Group wikis [can't be moved](../../api/project_repository_storage_moves.md#limitations) using the project
+ repository moves API.
-You can follow [this epic](https://gitlab.com/groups/gitlab-org/-/epics/2782) for updates.
+For updates, you can follow:
+
+- [The epic tracking feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782).
+- [The issue for adding the ability to move group wikis using the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
### Enable or disable group wikis **(CORE ONLY)**
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index f7275cec97c..92d31853d0b 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -47,7 +47,8 @@ version. The range of supported versions is based on the evaluation of:
- The versions supported by major managed Kubernetes providers.
- The versions [supported by the Kubernetes community](https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions).
-Currently, GitLab supports the following Kubernetes versions:
+GitLab supports the following Kubernetes versions, and you can upgrade your
+Kubernetes version to any supported version at any time:
- 1.17
- 1.16
diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb
index 3d2608c8c5a..4c4ec200060 100644
--- a/lib/api/discussions.rb
+++ b/lib/api/discussions.rb
@@ -8,7 +8,7 @@ module API
before { authenticate! }
- Helpers::DiscussionsHelpers.noteable_types.each do |noteable_type|
+ Helpers::DiscussionsHelpers.feature_category_per_noteable_type.each do |noteable_type, feature_category|
parent_type = noteable_type.parent_class.to_s.underscore
noteables_str = noteable_type.to_s.underscore.pluralize
noteables_path = noteable_type == Commit ? "repository/#{noteables_str}" : noteables_str
@@ -25,7 +25,7 @@ module API
use :pagination
end
- get ":id/#{noteables_path}/:noteable_id/discussions" do
+ get ":id/#{noteables_path}/:noteable_id/discussions", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
discussion_ids = paginate(noteable.discussion_ids_relation)
@@ -41,7 +41,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end
- get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
+ get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id])
@@ -91,7 +91,7 @@ module API
end
end
end
- post ":id/#{noteables_path}/:noteable_id/discussions" do
+ post ":id/#{noteables_path}/:noteable_id/discussions", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
type = params[:position] ? 'DiffNote' : 'DiscussionNote'
id_key = noteable.is_a?(Commit) ? :commit_id : :noteable_id
@@ -121,7 +121,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end
- get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
+ get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id])
@@ -141,7 +141,7 @@ module API
requires :body, type: String, desc: 'The content of a note'
optional :created_at, type: String, desc: 'The creation date of the note'
end
- post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
+ post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id])
first_note = notes.first
@@ -175,7 +175,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :note_id, type: Integer, desc: 'The ID of a note'
end
- get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
+ get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id])
@@ -192,7 +192,7 @@ module API
optional :resolved, type: Boolean, desc: 'Mark note resolved/unresolved'
exactly_one_of :body, :resolved
end
- put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
+ put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
if params[:resolved].nil?
@@ -210,7 +210,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :note_id, type: Integer, desc: 'The ID of a note'
end
- delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
+ delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
delete_note(noteable, params[:note_id])
@@ -225,7 +225,7 @@ module API
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :resolved, type: Boolean, desc: 'Mark discussion resolved/unresolved'
end
- put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
+ put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
resolve_discussion(noteable, params[:discussion_id], params[:resolved])
diff --git a/lib/api/entities/user_status.rb b/lib/api/entities/user_status.rb
index 9bc4cbf240f..1d5cc27e5ef 100644
--- a/lib/api/entities/user_status.rb
+++ b/lib/api/entities/user_status.rb
@@ -5,6 +5,7 @@ module API
class UserStatus < Grape::Entity
expose :emoji
expose :message
+ expose :availability
expose :message_html do |entity|
MarkupHelper.markdown_field(entity, :message)
end
diff --git a/lib/api/helpers/discussions_helpers.rb b/lib/api/helpers/discussions_helpers.rb
index 799d5582b38..3c0db1d0ea9 100644
--- a/lib/api/helpers/discussions_helpers.rb
+++ b/lib/api/helpers/discussions_helpers.rb
@@ -3,10 +3,15 @@
module API
module Helpers
module DiscussionsHelpers
- def self.noteable_types
+ def self.feature_category_per_noteable_type
# This is a method instead of a constant, allowing EE to more easily
# extend it.
- [Issue, Snippet, MergeRequest, Commit]
+ {
+ Issue => :issue_tracking,
+ Snippet => :snippets,
+ MergeRequest => :code_review,
+ Commit => :code_review
+ }
end
end
end
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index f61bcfe963e..6798c4d284b 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -5,10 +5,12 @@ module API
module NotesHelpers
include ::RendersNotes
- def self.noteable_types
- # This is a method instead of a constant, allowing EE to more easily
- # extend it.
- [Issue, MergeRequest, Snippet]
+ def self.feature_category_per_noteable_type
+ {
+ Issue => :issue_tracking,
+ MergeRequest => :code_review,
+ Snippet => :snippets
+ }
end
def update_note(noteable, note_id)
diff --git a/lib/api/import_bitbucket_server.rb b/lib/api/import_bitbucket_server.rb
index a0238c24f3b..ecd78c6e6db 100644
--- a/lib/api/import_bitbucket_server.rb
+++ b/lib/api/import_bitbucket_server.rb
@@ -2,6 +2,8 @@
module API
class ImportBitbucketServer < ::API::Base
+ feature_category :importers
+
helpers do
def client
@client ||= BitbucketServer::Client.new(credentials)
diff --git a/lib/api/import_github.rb b/lib/api/import_github.rb
index f3894818f28..c91a7700f58 100644
--- a/lib/api/import_github.rb
+++ b/lib/api/import_github.rb
@@ -2,6 +2,8 @@
module API
class ImportGithub < ::API::Base
+ feature_category :importers
+
rescue_from Octokit::Unauthorized, with: :provider_unauthorized
before do
diff --git a/lib/api/issue_links.rb b/lib/api/issue_links.rb
index db4979c9052..e938dbbae87 100644
--- a/lib/api/issue_links.rb
+++ b/lib/api/issue_links.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :issue_tracking
+
params do
requires :id, type: String, desc: 'The ID of a project'
requires :issue_iid, type: Integer, desc: 'The internal ID of a project issue'
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 25fce1bf473..864952d160e 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -6,10 +6,10 @@ module API
helpers Helpers::IssuesHelpers
helpers Helpers::RateLimiter
- feature_category :issue_tracking
-
before { authenticate_non_get! }
+ feature_category :issue_tracking
+
helpers do
params :negatable_issue_filter_params do
optional :labels, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
diff --git a/lib/api/job_artifacts.rb b/lib/api/job_artifacts.rb
index 536b361b308..1faa28d6f07 100644
--- a/lib/api/job_artifacts.rb
+++ b/lib/api/job_artifacts.rb
@@ -4,6 +4,8 @@ module API
class JobArtifacts < ::API::Base
before { authenticate_non_get! }
+ feature_category :continuous_integration
+
# EE::API::JobArtifacts would override the following helpers
helpers do
def authorize_download_artifacts!
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index bdb23b4a9be..51659c2e8a1 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :continuous_integration
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/keys.rb b/lib/api/keys.rb
index 2e4568029b5..fb1bedd5e92 100644
--- a/lib/api/keys.rb
+++ b/lib/api/keys.rb
@@ -5,6 +5,8 @@ module API
class Keys < ::API::Base
before { authenticate! }
+ feature_category :authentication_and_authorization
+
resource :keys do
desc 'Get single ssh key by id. Only available to admin users' do
success Entities::SSHKeyWithUser
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index c9a75583cee..a8fc277989e 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :issue_tracking
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index bfd152f70b1..ac8cc49c986 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -2,6 +2,8 @@
module API
class Lint < ::API::Base
+ feature_category :pipeline_authoring
+
namespace :ci do
desc 'Validation of .gitlab-ci.yml content'
params do
diff --git a/lib/api/markdown.rb b/lib/api/markdown.rb
index 97549abd273..de612ff8321 100644
--- a/lib/api/markdown.rb
+++ b/lib/api/markdown.rb
@@ -2,6 +2,8 @@
module API
class Markdown < ::API::Base
+ feature_category :not_owned
+
params do
requires :text, type: String, desc: "The markdown text to render"
optional :gfm, type: Boolean, desc: "Render text using GitLab Flavored Markdown"
diff --git a/lib/api/members.rb b/lib/api/members.rb
index c28b3b1cc7c..f2405589280 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :authentication_and_authorization
+
helpers ::API::Helpers::MembersHelpers
%w[group project].each do |source_type|
diff --git a/lib/api/merge_request_approvals.rb b/lib/api/merge_request_approvals.rb
index 14d6e3995ea..27ef0b9c7cd 100644
--- a/lib/api/merge_request_approvals.rb
+++ b/lib/api/merge_request_approvals.rb
@@ -4,6 +4,8 @@ module API
class MergeRequestApprovals < ::API::Base
before { authenticate_non_get! }
+ feature_category :code_review
+
helpers do
params :ee_approval_params do
end
diff --git a/lib/api/merge_request_diffs.rb b/lib/api/merge_request_diffs.rb
index 22023888bbd..0ffb38438eb 100644
--- a/lib/api/merge_request_diffs.rb
+++ b/lib/api/merge_request_diffs.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
+ feature_category :code_review
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index b24dd870c8b..d9640d95e32 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -8,6 +8,8 @@ module API
before { authenticate_non_get! }
+ feature_category :code_review
+
helpers Helpers::MergeRequestsHelpers
# EE::API::MergeRequests would override the following helpers
diff --git a/lib/api/metrics/dashboard/annotations.rb b/lib/api/metrics/dashboard/annotations.rb
index b6bc0af2202..0989340b3ea 100644
--- a/lib/api/metrics/dashboard/annotations.rb
+++ b/lib/api/metrics/dashboard/annotations.rb
@@ -4,6 +4,8 @@ module API
module Metrics
module Dashboard
class Annotations < ::API::Base
+ feature_category :metrics
+
desc 'Create a new monitoring dashboard annotation' do
success Entities::Metrics::Dashboard::Annotation
end
diff --git a/lib/api/metrics/user_starred_dashboards.rb b/lib/api/metrics/user_starred_dashboards.rb
index cb6e7099247..909f7f0405d 100644
--- a/lib/api/metrics/user_starred_dashboards.rb
+++ b/lib/api/metrics/user_starred_dashboards.rb
@@ -3,6 +3,8 @@
module API
module Metrics
class UserStarredDashboards < ::API::Base
+ feature_category :metrics
+
resource :projects do
desc 'Marks selected metrics dashboard as starred' do
success Entities::Metrics::UserStarredDashboard
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
index f98a1f6dd1d..25a901c18b6 100644
--- a/lib/api/namespaces.rb
+++ b/lib/api/namespaces.rb
@@ -6,6 +6,8 @@ module API
before { authenticate! }
+ feature_category :subgroups
+
helpers do
params :optional_list_params_ee do
# EE::API::Namespaces would override this helper
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 0db537ca616..d249431b2f8 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -7,7 +7,7 @@ module API
before { authenticate! }
- Helpers::NotesHelpers.noteable_types.each do |noteable_type|
+ Helpers::NotesHelpers.feature_category_per_noteable_type.each do |noteable_type, feature_category|
parent_type = noteable_type.parent_class.to_s.underscore
noteables_str = noteable_type.to_s.underscore.pluralize
@@ -29,7 +29,7 @@ module API
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
- get ":id/#{noteables_str}/:noteable_id/notes" do
+ get ":id/#{noteables_str}/:noteable_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
# We exclude notes that are cross-references and that cannot be viewed
@@ -57,7 +57,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note'
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
end
- get ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
+ get ":id/#{noteables_str}/:noteable_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id])
end
@@ -71,7 +71,7 @@ module API
optional :confidential, type: Boolean, desc: 'Confidentiality note flag, default is false'
optional :created_at, type: String, desc: 'The creation date of the note'
end
- post ":id/#{noteables_str}/:noteable_id/notes" do
+ post ":id/#{noteables_str}/:noteable_id/notes", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
opts = {
@@ -104,7 +104,7 @@ module API
optional :body, type: String, allow_blank: false, desc: 'The content of a note'
optional :confidential, type: Boolean, desc: 'Confidentiality note flag'
end
- put ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
+ put ":id/#{noteables_str}/:noteable_id/notes/:note_id", feature_category: feature_category do
noteable = find_noteable(noteable_type, params[:noteable_id])
update_note(noteable, params[:note_id])
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 2f54b8c0fae..54228373512 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -952,6 +952,7 @@ module API
params do
optional :emoji, type: String, desc: "The emoji to set on the status"
optional :message, type: String, desc: "The status message to set"
+ optional :availability, type: String, desc: "The availability of user to set"
end
put "status", feature_category: :users do
forbidden! unless can?(current_user, :update_user_status, current_user)
diff --git a/lib/gitlab/repository_size_checker.rb b/lib/gitlab/repository_size_checker.rb
index dbfec77cb18..64d58c15208 100644
--- a/lib/gitlab/repository_size_checker.rb
+++ b/lib/gitlab/repository_size_checker.rb
@@ -37,7 +37,9 @@ module Gitlab
# @param change_size [int] in bytes
def exceeded_size(change_size = 0)
- current_size + change_size - limit
+ size = current_size + change_size - limit
+
+ [size, 0].max
end
def error_message
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 5c31006122e..2f9183700a3 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -2831,6 +2831,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error has occurred fetching instructions"
+msgstr ""
+
msgid "An error occured while making the changes: %{error}"
msgstr ""
@@ -3952,6 +3955,12 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
msgstr ""
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
msgstr ""
@@ -14215,6 +14224,9 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a Runner"
+msgstr ""
+
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr ""
@@ -22974,6 +22986,12 @@ msgstr ""
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
@@ -23001,6 +23019,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -24408,6 +24429,9 @@ msgstr ""
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
msgstr ""
+msgid "Show Runner installation instructions"
+msgstr ""
+
msgid "Show all activity"
msgstr ""
diff --git a/package.json b/package.json
index c9a13178f0d..a9cb06b6487 100644
--- a/package.json
+++ b/package.json
@@ -114,7 +114,7 @@
"mock-apollo-client": "^0.4.0",
"monaco-editor": "^0.20.0",
"monaco-editor-webpack-plugin": "^1.9.0",
- "monaco-yaml": "^2.4.1",
+ "monaco-yaml": "^2.5.1",
"mousetrap": "1.6.5",
"pdfjs-dist": "^2.0.943",
"pikaday": "^1.8.0",
diff --git a/public/robots.txt b/public/robots.txt
index 50bddbc5a77..4029cae5145 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -36,6 +36,7 @@ User-Agent: *
Disallow: /*/new
Disallow: /*/edit
Disallow: /*/raw
+Disallow: /*/realtime_changes
# Group details
User-Agent: *
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index 87256269de2..9d6a4dbccee 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-cd "$(dirname "$0")/.."
+cd "$(dirname "$0")/.." || exit 1
echo "=> Linting documents at path $(pwd) as $(whoami)..."
echo
ERRORCODE=0
diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb
index 249e6322d1c..7a72a13febe 100644
--- a/spec/controllers/profiles_controller_spec.rb
+++ b/spec/controllers/profiles_controller_spec.rb
@@ -84,9 +84,10 @@ RSpec.describe ProfilesController, :request_store do
it 'allows setting a user status' do
sign_in(user)
- put :update, params: { user: { status: { message: 'Working hard!' } } }
+ put :update, params: { user: { status: { message: 'Working hard!', availability: 'busy' } } }
expect(user.reload.status.message).to eq('Working hard!')
+ expect(user.reload.status.availability).to eq('busy')
expect(response).to have_gitlab_http_status(:found)
end
diff --git a/spec/factories/terraform/state.rb b/spec/factories/terraform/state.rb
index e5cea9e252e..c54a8aedbc6 100644
--- a/spec/factories/terraform/state.rb
+++ b/spec/factories/terraform/state.rb
@@ -19,7 +19,7 @@ FactoryBot.define do
trait :with_version do
after(:create) do |state|
- create(:terraform_state_version, :with_file, terraform_state: state)
+ create(:terraform_state_version, terraform_state: state)
end
end
diff --git a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
index 4377cd0a60d..5d1feffe84a 100644
--- a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
+++ b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
@@ -8,12 +8,12 @@ import { trackAlertIntegrationsViewsOptions } from '~/alerts_settings/constants'
const mockIntegrations = [
{
- activated: true,
+ active: true,
name: 'Integration 1',
type: 'HTTP endpoint',
},
{
- activated: false,
+ active: false,
name: 'Integration 2',
type: 'HTTP endpoint',
},
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js
index ae12f6c9bef..50038ecb9ff 100644
--- a/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js
+++ b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js
@@ -3,8 +3,6 @@ import { GlForm, GlFormSelect, GlCollapse, GlFormInput } from '@gitlab/ui';
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_new.vue';
import { defaultAlertSettingsConfig } from './util';
-jest.mock('~/alerts_settings/services');
-
describe('AlertsSettingsFormNew', () => {
let wrapper;
diff --git a/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
index 74f3aa1d995..8c289cb0f1c 100644
--- a/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
+++ b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
@@ -1,17 +1,20 @@
-import { shallowMount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import { GlLoadingIcon } from '@gitlab/ui';
import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
import AlertsSettingsFormOld from '~/alerts_settings/components/alerts_settings_form_old.vue';
import AlertsSettingsFormNew from '~/alerts_settings/components/alerts_settings_form_new.vue';
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
import { defaultAlertSettingsConfig } from './util';
+import mockIntegrations from './mocks/integrations.json';
-jest.mock('~/alerts_settings/services');
-
-describe('AlertsSettingsFormWrapper', () => {
+describe('AlertsSettingsWrapper', () => {
let wrapper;
- const createComponent = (data = {}, provide = {}) => {
- wrapper = shallowMount(AlertsSettingsWrapper, {
+ const findLoader = () => wrapper.find(IntegrationsList).find(GlLoadingIcon);
+ const findIntegrations = () => wrapper.find(IntegrationsList).findAll('table tbody tr');
+
+ const createComponent = ({ data = {}, provide = {}, loading = false } = {}) => {
+ wrapper = mount(AlertsSettingsWrapper, {
data() {
return { ...data };
},
@@ -20,6 +23,16 @@ describe('AlertsSettingsFormWrapper', () => {
glFeatures: { httpIntegrationsList: false },
...provide,
},
+ mocks: {
+ $apollo: {
+ query: jest.fn(),
+ queries: {
+ integrations: {
+ loading,
+ },
+ },
+ },
+ },
});
};
@@ -30,19 +43,41 @@ describe('AlertsSettingsFormWrapper', () => {
}
});
- describe('with default values', () => {
- it('renders alerts integrations list and old form by default', () => {
+ describe('with httpIntegrationsList feature flag disabled', () => {
+ it('renders data driven alerts integrations list and old form by default', () => {
createComponent();
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(true);
expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(false);
});
+ });
- it('renders alerts integrations list and new form when httpIntegrationsList feature flag is enabled', () => {
- createComponent({}, { glFeatures: { httpIntegrationsList: true } });
+ describe('with httpIntegrationsList feature flag enabled', () => {
+ it('renders the GraphQL alerts integrations list and new form', () => {
+ createComponent({ provide: { glFeatures: { httpIntegrationsList: true } } });
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(false);
expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(true);
});
+
+ it('uses a loading state inside the IntegrationsList table', () => {
+ createComponent({
+ data: { integrations: {} },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: true,
+ });
+ expect(wrapper.find(IntegrationsList).exists()).toBe(true);
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('renders the IntegrationsList table using the API data', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations } },
+ provide: { glFeatures: { httpIntegrationsList: true } },
+ loading: false,
+ });
+ expect(findLoader().exists()).toBe(false);
+ expect(findIntegrations()).toHaveLength(mockIntegrations.length);
+ });
});
});
diff --git a/spec/frontend/alerts_settings/mocks/integrations.json b/spec/frontend/alerts_settings/mocks/integrations.json
new file mode 100644
index 00000000000..b1284fc55a2
--- /dev/null
+++ b/spec/frontend/alerts_settings/mocks/integrations.json
@@ -0,0 +1,38 @@
+[
+ {
+ "id": "gid://gitlab/AlertManagement::HttpIntegration/7",
+ "type": "HTTP",
+ "active": true,
+ "name": "test",
+ "url": "http://192.168.1.152:3000/root/autodevops/alerts/notify/test/eddd36969b2d3d6a.json",
+ "token": "7eb24af194116411ec8d66b58c6b0d2e",
+ "apiUrl": null
+ },
+ {
+ "id": "gid://gitlab/AlertManagement::HttpIntegration/6",
+ "type": "HTTP",
+ "active": false,
+ "name": "test",
+ "url": "http://192.168.1.152:3000/root/autodevops/alerts/notify/test/abce123.json",
+ "token": "8639e0ce06c731b00ee3e8dcdfd14fe0",
+ "apiUrl": null
+ },
+ {
+ "id": "gid://gitlab/AlertManagement::HttpIntegration/5",
+ "type": "HTTP",
+ "active": false,
+ "name": "test",
+ "url": "http://192.168.1.152:3000/root/autodevops/alerts/notify/test/bcd64c85f918a2e2.json",
+ "token": "5c8101533d970a55d5c105f8abff2192",
+ "apiUrl": null
+ },
+ {
+ "id": "gid://gitlab/PrometheusService/12",
+ "type": "PROMETHEUS",
+ "active": true,
+ "name": "Prometheus",
+ "url": "http://192.168.1.152:3000/root/autodevops/prometheus/alerts/notify.json",
+ "token": "0b18c37caa8fe980799b349916fe5ddf",
+ "apiUrl": "https://another-url-2.com"
+ }
+]
diff --git a/spec/frontend/static_site_editor/services/front_matterify_spec.js b/spec/frontend/static_site_editor/services/front_matterify_spec.js
index dbaedc30849..866897f21ef 100644
--- a/spec/frontend/static_site_editor/services/front_matterify_spec.js
+++ b/spec/frontend/static_site_editor/services/front_matterify_spec.js
@@ -11,6 +11,7 @@ describe('static_site_editor/services/front_matterify', () => {
const frontMatterifiedContent = {
source: content,
matter: yamlFrontMatterObj,
+ hasMatter: true,
spacing,
content: body,
delimiter: '---',
@@ -19,6 +20,7 @@ describe('static_site_editor/services/front_matterify', () => {
const frontMatterifiedBody = {
source: body,
matter: null,
+ hasMatter: false,
spacing: null,
content: body,
delimiter: null,
@@ -33,6 +35,12 @@ describe('static_site_editor/services/front_matterify', () => {
`('returns $target from $frontMatterified', ({ frontMatterified, target }) => {
expect(frontMatterified).toEqual(target);
});
+
+ it('should throw when matter is invalid', () => {
+ const invalidContent = `---\nkey: val\nkeyNoVal\n---\n${body}`;
+
+ expect(() => frontMatterify(invalidContent)).toThrow();
+ });
});
describe('stringify', () => {
diff --git a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
new file mode 100644
index 00000000000..01f7f3d49c7
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
@@ -0,0 +1,107 @@
+export const mockGraphqlRunnerPlatforms = {
+ data: {
+ runnerPlatforms: {
+ nodes: [
+ {
+ name: 'linux',
+ humanReadableName: 'Linux',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: '386',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: 'arm',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: 'arm64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm64',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'osx',
+ humanReadableName: 'macOS',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'windows',
+ humanReadableName: 'Windows',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: '386',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-386.exe',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'docker',
+ humanReadableName: 'Docker',
+ architectures: null,
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'kubernetes',
+ humanReadableName: 'Kubernetes',
+ architectures: null,
+ __typename: 'RunnerPlatform',
+ },
+ ],
+ __typename: 'RunnerPlatformConnection',
+ },
+ project: { id: 'gid://gitlab/Project/1', __typename: 'Project' },
+ group: null,
+ },
+};
+
+export const mockGraphqlInstructions = {
+ data: {
+ runnerSetup: {
+ installInstructions:
+ "# Download the binary for your system\nsudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64\n\n# Give it permissions to execute\nsudo chmod +x /usr/local/bin/gitlab-runner\n\n# Create a GitLab CI user\nsudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash\n\n# Install and run as service\nsudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner\nsudo gitlab-runner start\n",
+ registerInstructions:
+ 'sudo gitlab-runner register --url http://192.168.1.81:3000/ --registration-token GE5gsjeep_HAtBf9s3Yz',
+ __typename: 'RunnerSetup',
+ },
+ },
+};
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
new file mode 100644
index 00000000000..afbcee506c7
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
@@ -0,0 +1,119 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
+import getRunnerPlatforms from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructions from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql';
+
+import { mockGraphqlRunnerPlatforms, mockGraphqlInstructions } from './mock_data';
+
+const projectPath = 'gitlab-org/gitlab';
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('RunnerInstructions component', () => {
+ let wrapper;
+ let fakeApollo;
+
+ const findModalButton = () => wrapper.find('[data-testid="show-modal-button"]');
+ const findPlatformButtons = () => wrapper.findAll('[data-testid="platform-button"]');
+ const findArchitectureDropdownItems = () =>
+ wrapper.findAll('[data-testid="architecture-dropdown-item"]');
+ const findBinaryInstructionsSection = () => wrapper.find('[data-testid="binary-instructions"]');
+ const findRunnerInstructionsSection = () => wrapper.find('[data-testid="runner-instructions"]');
+
+ beforeEach(() => {
+ const requestHandlers = [
+ [getRunnerPlatforms, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)],
+ [getRunnerSetupInstructions, jest.fn().mockResolvedValue(mockGraphqlInstructions)],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+
+ wrapper = shallowMount(RunnerInstructions, {
+ provide: {
+ projectPath,
+ },
+ localVue,
+ apolloProvider: fakeApollo,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should show the "Show Runner installation instructions" button', () => {
+ const button = findModalButton();
+
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe('Show Runner installation instructions');
+ });
+
+ it('should contain a number of platforms buttons', () => {
+ const buttons = findPlatformButtons();
+
+ expect(buttons).toHaveLength(mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes.length);
+ });
+
+ it('should contain a number of dropdown items for the architecture options', () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ return wrapper.vm.$nextTick(() => {
+ const dropdownItems = findArchitectureDropdownItems();
+
+ expect(dropdownItems).toHaveLength(
+ mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes.length,
+ );
+ });
+ });
+
+ it('should display the binary installation instructions for a selected architecture', async () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownItem = findArchitectureDropdownItems().at(0);
+ dropdownItem.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const runner = findBinaryInstructionsSection();
+
+ expect(runner.text()).toEqual(
+ expect.stringContaining('sudo chmod +x /usr/local/bin/gitlab-runner'),
+ );
+ expect(runner.text()).toEqual(
+ expect.stringContaining(
+ `sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash`,
+ ),
+ );
+ expect(runner.text()).toEqual(
+ expect.stringContaining(
+ 'sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner',
+ ),
+ );
+ expect(runner.text()).toEqual(expect.stringContaining('sudo gitlab-runner start'));
+ });
+
+ it('should display the runner register instructions for a selected architecture', async () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownItem = findArchitectureDropdownItems().at(0);
+ dropdownItem.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const runner = findRunnerInstructionsSection();
+
+ expect(runner.text()).toEqual(
+ expect.stringContaining(mockGraphqlInstructions.data.runnerSetup.registerInstructions),
+ );
+ });
+});
diff --git a/spec/graphql/types/availability_enum_spec.rb b/spec/graphql/types/availability_enum_spec.rb
new file mode 100644
index 00000000000..a9bdf5e4da6
--- /dev/null
+++ b/spec/graphql/types/availability_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['AvailabilityEnum'] do
+ specify { expect(described_class.graphql_name).to eq('AvailabilityEnum') }
+
+ it 'exposes all the existing access levels' do
+ expect(described_class.values.keys).to match_array(%w[NOT_SET BUSY])
+ end
+end
diff --git a/spec/graphql/types/terraform/state_type_spec.rb b/spec/graphql/types/terraform/state_type_spec.rb
index 51508208046..9f65bb926d7 100644
--- a/spec/graphql/types/terraform/state_type_spec.rb
+++ b/spec/graphql/types/terraform/state_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['TerraformState'] do
it { expect(described_class).to require_graphql_authorizations(:read_terraform_state) }
describe 'fields' do
- let(:fields) { %i[id name locked_by_user locked_at created_at updated_at] }
+ let(:fields) { %i[id name locked_by_user locked_at latest_version created_at updated_at] }
it { expect(described_class).to have_graphql_fields(fields) }
@@ -17,5 +17,8 @@ RSpec.describe GitlabSchema.types['TerraformState'] do
it { expect(described_class.fields['lockedAt'].type).not_to be_non_null }
it { expect(described_class.fields['createdAt'].type).to be_non_null }
it { expect(described_class.fields['updatedAt'].type).to be_non_null }
+
+ it { expect(described_class.fields['latestVersion'].type).not_to be_non_null }
+ it { expect(described_class.fields['latestVersion'].complexity).to eq(3) }
end
end
diff --git a/spec/graphql/types/terraform/state_version_type_spec.rb b/spec/graphql/types/terraform/state_version_type_spec.rb
new file mode 100644
index 00000000000..2fa41f47028
--- /dev/null
+++ b/spec/graphql/types/terraform/state_version_type_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['TerraformStateVersion'] do
+ it { expect(described_class.graphql_name).to eq('TerraformStateVersion') }
+ it { expect(described_class).to require_graphql_authorizations(:read_terraform_state) }
+
+ describe 'fields' do
+ let(:fields) { %i[id created_by_user created_at updated_at] }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+
+ it { expect(described_class.fields['id'].type).to be_non_null }
+ it { expect(described_class.fields['createdByUser'].type).not_to be_non_null }
+ it { expect(described_class.fields['createdAt'].type).to be_non_null }
+ it { expect(described_class.fields['updatedAt'].type).to be_non_null }
+ end
+end
diff --git a/spec/graphql/types/user_status_type_spec.rb b/spec/graphql/types/user_status_type_spec.rb
index c4421a9cc10..ced9c40d552 100644
--- a/spec/graphql/types/user_status_type_spec.rb
+++ b/spec/graphql/types/user_status_type_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe Types::UserStatusType do
emoji
message
message_html
+ availability
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/helpers/operations_helper_spec.rb b/spec/helpers/operations_helper_spec.rb
index 8d2fc643caa..2ed52716802 100644
--- a/spec/helpers/operations_helper_spec.rb
+++ b/spec/helpers/operations_helper_spec.rb
@@ -43,7 +43,8 @@ RSpec.describe OperationsHelper do
'prometheus_api_url' => nil,
'prometheus_activated' => 'false',
'prometheus_url' => notify_project_prometheus_alerts_url(project, format: :json),
- 'disabled' => 'false'
+ 'disabled' => 'false',
+ 'project_path' => project_path(project)
)
end
end
diff --git a/spec/lib/api/every_api_endpoint_spec.rb b/spec/lib/api/every_api_endpoint_spec.rb
index 4a8998b89f9..ac424a511c0 100644
--- a/spec/lib/api/every_api_endpoint_spec.rb
+++ b/spec/lib/api/every_api_endpoint_spec.rb
@@ -31,8 +31,13 @@ RSpec.describe 'Every API endpoint' do
::API::FeatureFlagsUserLists, ::API::Features, ::API::Files, ::API::FreezePeriods,
::API::GroupBoards, ::API::GroupClusters, ::API::GroupExport, ::API::GroupImport,
::API::GroupLabels, ::API::GroupMilestones, ::API::Groups,
- ::API::GroupContainerRepositories, ::API::GroupVariables
-
+ ::API::GroupContainerRepositories, ::API::GroupVariables,
+ ::API::ImportBitbucketServer, ::API::ImportGithub, ::API::IssueLinks,
+ ::API::Issues, ::API::JobArtifacts, ::API::Jobs, ::API::Keys, ::API::Labels,
+ ::API::Lint, ::API::Markdown, ::API::Members, ::API::MergeRequestDiffs,
+ ::API::MergeRequests, ::API::MergeRequestApprovals, ::API::Metrics::Dashboard::Annotations,
+ ::API::Metrics::UserStarredDashboards, ::API::Namespaces, ::API::Notes,
+ ::API::Discussions
]
next unless completed_classes.include?(klass)
diff --git a/spec/policies/terraform/state_version_policy_spec.rb b/spec/policies/terraform/state_version_policy_spec.rb
new file mode 100644
index 00000000000..6614e073332
--- /dev/null
+++ b/spec/policies/terraform/state_version_policy_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Terraform::StateVersionPolicy do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:terraform_state) { create(:terraform_state, :with_version, project: project)}
+
+ subject { described_class.new(user, terraform_state.latest_version) }
+
+ describe 'rules' do
+ context 'no access' do
+ let(:user) { create(:user) }
+
+ it { is_expected.to be_disallowed(:read_terraform_state) }
+ it { is_expected.to be_disallowed(:admin_terraform_state) }
+ end
+
+ context 'developer' do
+ let(:user) { create(:user, developer_projects: [project]) }
+
+ it { is_expected.to be_allowed(:read_terraform_state) }
+ it { is_expected.to be_disallowed(:admin_terraform_state) }
+ end
+
+ context 'maintainer' do
+ let(:user) { create(:user, maintainer_projects: [project]) }
+
+ it { is_expected.to be_allowed(:read_terraform_state) }
+ it { is_expected.to be_allowed(:admin_terraform_state) }
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/terraform/states_spec.rb b/spec/requests/api/graphql/project/terraform/states_spec.rb
index 533f913926c..c72af19a7a3 100644
--- a/spec/requests/api/graphql/project/terraform/states_spec.rb
+++ b/spec/requests/api/graphql/project/terraform/states_spec.rb
@@ -6,7 +6,8 @@ RSpec.describe 'query terraform states' do
include GraphqlHelpers
let_it_be(:project) { create(:project) }
- let_it_be(:terraform_state) { create(:terraform_state, :locked, project: project) }
+ let_it_be(:terraform_state) { create(:terraform_state, :with_version, :locked, project: project) }
+ let_it_be(:latest_version) { terraform_state.latest_version }
let(:query) do
graphql_query_for(:project, { fullPath: project.full_path },
@@ -20,6 +21,16 @@ RSpec.describe 'query terraform states' do
createdAt
updatedAt
+ latestVersion {
+ id
+ createdAt
+ updatedAt
+
+ createdByUser {
+ id
+ }
+ }
+
lockedByUser {
id
}
@@ -37,13 +48,19 @@ RSpec.describe 'query terraform states' do
it 'returns terraform state data', :aggregate_failures do
state = data.dig('nodes', 0)
+ version = state['latestVersion']
expect(state['id']).to eq(terraform_state.to_global_id.to_s)
expect(state['name']).to eq(terraform_state.name)
- expect(state['lockedAt']).to eq(terraform_state.locked_at.strftime('%Y-%m-%dT%H:%M:%SZ'))
- expect(state['createdAt']).to eq(terraform_state.created_at.strftime('%Y-%m-%dT%H:%M:%SZ'))
- expect(state['updatedAt']).to eq(terraform_state.updated_at.strftime('%Y-%m-%dT%H:%M:%SZ'))
+ expect(state['lockedAt']).to eq(terraform_state.locked_at.iso8601)
+ expect(state['createdAt']).to eq(terraform_state.created_at.iso8601)
+ expect(state['updatedAt']).to eq(terraform_state.updated_at.iso8601)
expect(state.dig('lockedByUser', 'id')).to eq(terraform_state.locked_by_user.to_global_id.to_s)
+
+ expect(version['id']).to eq(latest_version.to_global_id.to_s)
+ expect(version['createdAt']).to eq(terraform_state.created_at.iso8601)
+ expect(version['updatedAt']).to eq(terraform_state.updated_at.iso8601)
+ expect(version.dig('createdByUser', 'id')).to eq(latest_version.created_by_user.to_global_id.to_s)
end
it 'returns count of terraform states' do
diff --git a/spec/requests/api/graphql/user_query_spec.rb b/spec/requests/api/graphql/user_query_spec.rb
index 79debd0b7ef..d64fd3868c2 100644
--- a/spec/requests/api/graphql/user_query_spec.rb
+++ b/spec/requests/api/graphql/user_query_spec.rb
@@ -59,6 +59,7 @@ RSpec.describe 'getting user information' do
let(:user_params) { { username: user.username } }
before do
+ create(:user_status, user: user)
post_graphql(query, current_user: current_user)
end
@@ -76,9 +77,15 @@ RSpec.describe 'getting user information' do
'username' => presenter.username,
'webUrl' => presenter.web_url,
'avatarUrl' => presenter.avatar_url,
- 'status' => presenter.status,
'email' => presenter.email
))
+
+ expect(graphql_data['user']['status']).to match(
+ a_hash_including(
+ 'emoji' => presenter.status.emoji,
+ 'message' => presenter.status.message,
+ 'availability' => presenter.status.availability.upcase
+ ))
end
describe 'assignedMergeRequests' do
diff --git a/spec/requests/robots_txt_spec.rb b/spec/requests/robots_txt_spec.rb
index b8e02827ba1..a8be4093a71 100644
--- a/spec/requests/robots_txt_spec.rb
+++ b/spec/requests/robots_txt_spec.rb
@@ -79,7 +79,9 @@ RSpec.describe 'Robots.txt Requests', :aggregate_failures do
'/foo/bar/-/incidents',
'/foo/bar/-/value_stream_analytics',
'/foo/bar/-/analytics',
- '/foo/bar/insights'
+ '/foo/bar/insights',
+ '/foo/bar/-/issues/123/realtime_changes',
+ '/groups/group/-/epics/123/realtime_changes'
]
requests.each do |request|
diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
index cfe8e863223..1b829df6e6a 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -241,18 +241,6 @@ RSpec.describe Projects::LfsPointers::LfsDownloadService do
context 'and first fragments are the same' do
let(:lfs_content) { existing_lfs_object.file.read }
- context 'when lfs_link_existing_object feature flag disabled' do
- before do
- stub_feature_flags(lfs_link_existing_object: false)
- end
-
- it 'does not call link_existing_lfs_object!' do
- expect(subject).not_to receive(:link_existing_lfs_object!)
-
- subject.execute
- end
- end
-
it 'returns success' do
expect(subject.execute).to eq({ status: :success })
end
diff --git a/spec/services/users/set_status_service_spec.rb b/spec/services/users/set_status_service_spec.rb
index 54489adceb0..319723b5201 100644
--- a/spec/services/users/set_status_service_spec.rb
+++ b/spec/services/users/set_status_service_spec.rb
@@ -9,13 +9,14 @@ RSpec.describe Users::SetStatusService do
describe '#execute' do
context 'when params are set' do
- let(:params) { { emoji: 'taurus', message: 'a random status' } }
+ let(:params) { { emoji: 'taurus', message: 'a random status', availability: 'busy' } }
it 'creates a status' do
service.execute
expect(current_user.status.emoji).to eq('taurus')
expect(current_user.status.message).to eq('a random status')
+ expect(current_user.status.availability).to eq('busy')
end
it 'updates a status if it already existed' do
@@ -25,6 +26,26 @@ RSpec.describe Users::SetStatusService do
expect(current_user.status.message).to eq('a random status')
end
+ it 'returns true' do
+ create(:user_status, user: current_user)
+ expect(service.execute).to be(true)
+ end
+
+ context 'when the given availability value is not valid' do
+ let(:params) { { availability: 'not a valid value' } }
+
+ it 'does not update the status' do
+ user_status = create(:user_status, user: current_user)
+
+ expect { service.execute }.not_to change { user_status.reload }
+ end
+
+ it 'returns false' do
+ create(:user_status, user: current_user)
+ expect(service.execute).to be(false)
+ end
+ end
+
context 'for another user' do
let(:target_user) { create(:user) }
let(:params) do
diff --git a/spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb
index bb909ffe82a..30413f206f8 100644
--- a/spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/repository_size_checker_shared_examples.rb
@@ -17,35 +17,58 @@ RSpec.shared_examples 'checker size not over limit' do
end
RSpec.shared_examples 'checker size exceeded' do
- context 'when current size is below or equal to the limit' do
- let(:current_size) { 50 }
+ context 'when no change size provided' do
+ context 'when current size is below the limit' do
+ let(:current_size) { limit - 1 }
- it 'returns zero' do
- expect(subject.exceeded_size).to eq(0)
+ it 'returns zero' do
+ expect(subject.exceeded_size).to eq(0)
+ end
end
- end
- context 'when current size is over the limit' do
- let(:current_size) { 51 }
+ context 'when current size is equal to the limit' do
+ let(:current_size) { limit }
- it 'returns zero' do
- expect(subject.exceeded_size).to eq(1.megabytes)
+ it 'returns zero' do
+ expect(subject.exceeded_size).to eq(0)
+ end
end
- end
- context 'when change size will be over the limit' do
- let(:current_size) { 50 }
+ context 'when current size is over the limit' do
+ let(:current_size) { limit + 1 }
+ let(:total_repository_size_excess) { 1 }
- it 'returns zero' do
- expect(subject.exceeded_size(1.megabytes)).to eq(1.megabytes)
+ it 'returns a positive number' do
+ expect(subject.exceeded_size).to eq(1.megabyte)
+ end
end
end
- context 'when change size will not be over the limit' do
- let(:current_size) { 49 }
+ context 'when a change size is provided' do
+ let(:change_size) { 1.megabyte }
+
+ context 'when change size will be over the limit' do
+ let(:current_size) { limit }
+
+ it 'returns a positive number' do
+ expect(subject.exceeded_size(change_size)).to eq(1.megabyte)
+ end
+ end
+
+ context 'when change size will be at the limit' do
+ let(:current_size) { limit - 1 }
+
+ it 'returns zero' do
+ expect(subject.exceeded_size(change_size)).to eq(0)
+ end
+ end
+
+ context 'when change size will be under the limit' do
+ let(:current_size) { limit - 2 }
- it 'returns zero' do
- expect(subject.exceeded_size(1.megabytes)).to eq(0)
+ it 'returns zero' do
+ expect(subject.exceeded_size(change_size)).to eq(0)
+ end
end
end
end
diff --git a/yarn.lock b/yarn.lock
index 633694cc093..d2939cb94c0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1659,6 +1659,13 @@ after@0.8.2:
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
+agent-base@4, agent-base@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
+ integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
aggregate-error@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0"
@@ -3833,7 +3840,14 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
dependencies:
ms "2.0.0"
-debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
+debug@3.1.0, debug@~3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+ dependencies:
+ ms "2.0.0"
+
+debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -3847,13 +3861,6 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
dependencies:
ms "^2.1.1"
-debug@~3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
- integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
- dependencies:
- ms "2.0.0"
-
decamelize-keys@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
@@ -4446,11 +4453,23 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
+es6-promise@^4.0.3:
+ version "4.2.8"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+ integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
+
es6-promise@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6"
integrity sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+ integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
+ dependencies:
+ es6-promise "^4.0.3"
+
escape-goat@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
@@ -5897,6 +5916,14 @@ http-errors@~1.6.2:
setprototypeof "1.0.3"
statuses ">= 1.3.1 < 2"
+http-proxy-agent@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
+ integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
+ dependencies:
+ agent-base "4"
+ debug "3.1.0"
+
http-proxy-middleware@0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a"
@@ -5930,6 +5957,14 @@ https-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
+https-proxy-agent@^2.2.3:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
+ integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
+ dependencies:
+ agent-base "^4.3.0"
+ debug "^3.1.0"
+
human-signals@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
@@ -7166,7 +7201,7 @@ js-cookie@^2.2.1:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-yaml@^3.12.0, js-yaml@^3.13.1, js-yaml@~3.13.1:
+js-yaml@^3.13.1, js-yaml@~3.13.1:
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
@@ -7305,7 +7340,12 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
-jsonc-parser@^2.2.1, jsonc-parser@~2.2.0:
+jsonc-parser@^2.2.1, jsonc-parser@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342"
+ integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==
+
+jsonc-parser@~2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc"
integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==
@@ -8381,17 +8421,12 @@ monaco-editor@0.20.0, monaco-editor@^0.20.0:
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
integrity sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ==
-monaco-yaml@^2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-2.4.1.tgz#f0d3384b1f10cc7af2b60e3a30b0adc6683b728a"
- integrity sha512-Q0Yj6FNok97AslptS1OVfyX07rJ5uhOYsHKaVoU0usiUqeL7gzl6l8TL8W3QGdwCKm4WhfKpJ9bqPDtiQvCirg==
+monaco-yaml@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-2.5.1.tgz#af9303a4aa6e3b94db62b8a8659362f31944590d"
+ integrity sha512-U+zIAcwnQzlUgy6vdzFdNf5PToFzuz099FxYmUxIeen9GTiq6XYDX9mmXSR31mMrgiSaU5a2bGEyG4p2fbW/7A==
dependencies:
- js-yaml "^3.12.0"
- vscode-json-languageservice "^3.4.11"
- vscode-languageserver "^5.2.1"
- vscode-uri "^2.1.1"
- optionalDependencies:
- prettier "^1.19.1"
+ yaml-language-server "^0.11.1"
mousetrap@1.6.5:
version "1.6.5"
@@ -9501,15 +9536,15 @@ pretender@^3.4.3:
fake-xml-http-request "^2.1.1"
route-recognizer "^0.3.3"
-prettier@1.18.2:
+prettier@1.18.2, prettier@^1.18.2:
version "1.18.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
-prettier@^1.18.2, prettier@^1.19.1:
- version "1.19.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
- integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
+prettier@2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
+ integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
pretty-format@^25.2.1, pretty-format@^25.5.0:
version "25.5.0"
@@ -10175,6 +10210,15 @@ replace-ext@1.0.0:
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
+request-light@^0.2.4:
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.5.tgz#38a3da7b2e56f7af8cbba57e8a94930ee2380746"
+ integrity sha512-eBEh+GzJAftUnex6tcL6eV2JCifY0+sZMIUpUPOVXbs2nV5hla4ZMmO3icYKGuGVuQ2zHE9evh4OrRcH4iyYYw==
+ dependencies:
+ http-proxy-agent "^2.1.0"
+ https-proxy-agent "^2.2.3"
+ vscode-nls "^4.1.1"
+
request-promise-core@1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
@@ -12247,15 +12291,15 @@ void-elements@^2.0.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
-vscode-json-languageservice@^3.4.11:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.7.0.tgz#0174417f139cf41dd60c84538fd052385bfb46f6"
- integrity sha512-nGLqcBhTjdfkl8Dz9sYGK/ZCTjscYFoIjYw+qqkWB+vyNfM0k/AyIoT73DQvB/PArteCKjEVfQUF72GRZEDSbQ==
+vscode-json-languageservice@^3.6.0:
+ version "3.9.1"
+ resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.9.1.tgz#f72b581f8cd2bd9b47445ccf8b0ddcde6aba7483"
+ integrity sha512-oJkknkdCVitQ5XPSRa0weHjUxt8eSCptaL+MBQQlRsa6Nb8XnEY0S5wYnLUFHzEvKzwt01/LKk8LdOixWEXkNA==
dependencies:
- jsonc-parser "^2.2.1"
+ jsonc-parser "^2.3.1"
vscode-languageserver-textdocument "^1.0.1"
- vscode-languageserver-types "^3.15.1"
- vscode-nls "^4.1.2"
+ vscode-languageserver-types "3.16.0-next.2"
+ vscode-nls "^5.0.0"
vscode-uri "^2.1.2"
vscode-jsonrpc@^4.0.0:
@@ -12281,6 +12325,11 @@ vscode-languageserver-types@3.14.0:
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743"
integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==
+vscode-languageserver-types@3.16.0-next.2:
+ version "3.16.0-next.2"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083"
+ integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==
+
vscode-languageserver-types@^3.15.1:
version "3.15.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz#17be71d78d2f6236d414f0001ce1ef4d23e6b6de"
@@ -12294,11 +12343,16 @@ vscode-languageserver@^5.2.1:
vscode-languageserver-protocol "3.14.1"
vscode-uri "^1.0.6"
-vscode-nls@^4.1.2:
+vscode-nls@^4.1.1, vscode-nls@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167"
integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==
+vscode-nls@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840"
+ integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==
+
vscode-uri@^1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.8.tgz#9769aaececae4026fb6e22359cb38946580ded59"
@@ -12869,6 +12923,28 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+yaml-ast-parser-custom-tags@0.0.43:
+ version "0.0.43"
+ resolved "https://registry.yarnpkg.com/yaml-ast-parser-custom-tags/-/yaml-ast-parser-custom-tags-0.0.43.tgz#46968145ce4e24cb03c3312057f0f141b93a7d02"
+ integrity sha512-R5063FF/JSAN6qXCmylwjt9PcDH6M0ExEme/nJBzLspc6FJDmHHIqM7xh2WfEmsTJqClF79A9VkXjkAqmZw9SQ==
+
+yaml-language-server@^0.11.1:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/yaml-language-server/-/yaml-language-server-0.11.1.tgz#4ddc72eb9a6dd7dc41f31af2a8f5c72cce456cc9"
+ integrity sha512-N3Tu3g4O6ZWV7W0LVsNk62DtKJDQkbnPZRDd7ntaAeEl8QkxL1vnMunI26uzDU4PwwG4tPJ8g/VRS6U+fVp/6A==
+ dependencies:
+ js-yaml "^3.13.1"
+ jsonc-parser "^2.2.1"
+ request-light "^0.2.4"
+ vscode-json-languageservice "^3.6.0"
+ vscode-languageserver "^5.2.1"
+ vscode-languageserver-types "^3.15.1"
+ vscode-nls "^4.1.2"
+ vscode-uri "^2.1.1"
+ yaml-ast-parser-custom-tags "0.0.43"
+ optionalDependencies:
+ prettier "2.0.5"
+
yargs-parser@20.x:
version "20.2.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.1.tgz#28f3773c546cdd8a69ddae68116b48a5da328e77"