diff options
112 files changed, 670 insertions, 1747 deletions
diff --git a/.gitlab/ci/package-and-test/rules.gitlab-ci.yml b/.gitlab/ci/package-and-test/rules.gitlab-ci.yml index 64d56cec21a..06290db2f6a 100644 --- a/.gitlab/ci/package-and-test/rules.gitlab-ci.yml +++ b/.gitlab/ci/package-and-test/rules.gitlab-ci.yml @@ -43,9 +43,9 @@ .rules:dont-interrupt: rules: - - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH + - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_MERGE_REQUEST_IID == null' allow_failure: true - - if: $CI_MERGE_REQUEST_IID + - if: '$CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached"' when: manual allow_failure: true diff --git a/.gitlab/ci/review-apps/rules.gitlab-ci.yml b/.gitlab/ci/review-apps/rules.gitlab-ci.yml index 49343c98547..4eb5e7060cb 100644 --- a/.gitlab/ci/review-apps/rules.gitlab-ci.yml +++ b/.gitlab/ci/review-apps/rules.gitlab-ci.yml @@ -8,7 +8,7 @@ # No specific specs in mr pipeline .all-specs-mr: &all-specs-mr - if: $CI_MERGE_REQUEST_IID && $QA_TESTS == "" + if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $QA_TESTS == ""' when: manual # Triggered by change pattern diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 80cb590fde5..93913e204be 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -21,7 +21,7 @@ if: '$FORCE_GITLAB_CI' .if-default-refs: &if-default-refs - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ || $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/ || $CI_COMMIT_REF_NAME =~ /^security\// || $CI_COMMIT_REF_NAME == "ruby2" || $CI_MERGE_REQUEST_IID || $CI_COMMIT_TAG || $FORCE_GITLAB_CI' + if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ || $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/ || $CI_COMMIT_REF_NAME =~ /^security\// || $CI_COMMIT_REF_NAME == "ruby2" || ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") || $CI_COMMIT_TAG || $FORCE_GITLAB_CI' .if-default-branch-refs: &if-default-branch-refs if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_MERGE_REQUEST_IID == null' @@ -30,33 +30,33 @@ if: '$CI_COMMIT_BRANCH =~ /^\d+-\d+-auto-deploy-\d+$/' .if-default-branch-or-tag: &if-default-branch-or-tag - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG' + if: '($CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_MERGE_REQUEST_IID == null) || $CI_COMMIT_TAG' .if-tag: &if-tag if: '$CI_COMMIT_TAG' .if-merge-request: &if-merge-request - if: '$CI_MERGE_REQUEST_IID' + if: '$CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached"' # Once https://gitlab.com/gitlab-org/gitlab/-/issues/373904 is implemented, we should be able to change this back to -# if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_APPROVALS_COUNT > 0' +# if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_APPROVALS_COUNT > 0' # or any similar condition to check that the MR has *any* approval (not just required approval). # # Temprorarily adding || $CI_MERGE_REQUEST_LABELS =~ /pipeline:run-full-rspec/ for backward compatibility, # remove once https://gitlab.com/gitlab-org/quality/quality-engineering/team-tasks/-/issues/1557 is fully rolled out .if-merge-request-approved: &if-merge-request-approved - if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_LABELS =~ /pipeline:mr-approved/ || $CI_MERGE_REQUEST_LABELS =~ /pipeline:run-full-rspec/' + if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS =~ /pipeline:mr-approved/ || $CI_MERGE_REQUEST_LABELS =~ /pipeline:run-full-rspec/' # Temprorarily adding && $CI_MERGE_REQUEST_LABELS !~ /pipeline:run-full-rspec/ for backward compatibility, # remove once https://gitlab.com/gitlab-org/quality/quality-engineering/team-tasks/-/issues/1557 is fully rolled out .if-merge-request-not-approved: &if-merge-request-not-approved - if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_LABELS !~ /pipeline:mr-approved/ && $CI_MERGE_REQUEST_LABELS !~ /pipeline:run-full-rspec/' + if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS !~ /pipeline:mr-approved/ && $CI_MERGE_REQUEST_LABELS !~ /pipeline:run-full-rspec/' .if-automated-merge-request: &if-automated-merge-request if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "release-tools/update-gitaly" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /stable-ee$/' .if-merge-request-targeting-stable-branch: &if-merge-request-targeting-stable-branch - if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/' + if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/' .if-merge-request-labels-run-in-ruby2: &if-merge-request-labels-run-in-ruby2 if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby2/' @@ -104,10 +104,10 @@ if: '$CI_MERGE_REQUEST_LABELS =~ /frontend/ && $CI_MERGE_REQUEST_LABELS =~ /feature flag/' .if-security-merge-request: &if-security-merge-request - if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security" && $CI_MERGE_REQUEST_IID' + if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security" && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")' .if-fork-merge-request: &if-fork-merge-request - if: '$CI_PROJECT_NAMESPACE !~ /^gitlab(-org)?($|\/)/ && $CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_LABELS !~ /pipeline:run-all-rspec/' + if: '$CI_PROJECT_NAMESPACE !~ /^gitlab(-org)?($|\/)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS !~ /pipeline:run-all-rspec/' .if-schedule-pipeline: &if-schedule-pipeline if: '$CI_PIPELINE_SOURCE == "schedule"' @@ -140,16 +140,16 @@ if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH' .if-dot-com-gitlab-org-merge-request: &if-dot-com-gitlab-org-merge-request - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_MERGE_REQUEST_IID' + if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")' .if-dot-com-gitlab-org-and-security-merge-request: &if-dot-com-gitlab-org-and-security-merge-request - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_MERGE_REQUEST_IID' + if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")' .if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified: &if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_MERGE_REQUEST_IID && $QA_TESTS' + if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $QA_TESTS' .if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e: &if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_MERGE_REQUEST_IID && $QA_MANUAL_FF_PACKAGE_AND_QA' + if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $QA_MANUAL_FF_PACKAGE_AND_QA' .if-dot-com-gitlab-org-and-security-tag: &if-dot-com-gitlab-org-and-security-tag if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_COMMIT_TAG' @@ -1062,7 +1062,7 @@ - <<: *if-default-branch-refs changes: *frontend-build-patterns allow_failure: true - - if: '$DANGER_GITLAB_API_TOKEN && $CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH' + - if: '$DANGER_GITLAB_API_TOKEN && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH' changes: *frontend-build-patterns allow_failure: true diff --git a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue index 967125c7b0a..d468c82893d 100644 --- a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue +++ b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue @@ -14,6 +14,7 @@ import { GlModal, GlSprintf, } from '@gitlab/ui'; +import { helpPagePath } from '~/helpers/help_page_helper'; import { getCookie, setCookie } from '~/lib/utils/common_utils'; import { __ } from '~/locale'; import Tracking from '~/tracking'; @@ -31,6 +32,7 @@ import { EVENT_ACTION, EXPANDED_VARIABLES_NOTE, EDIT_VARIABLE_ACTION, + FLAG_LINK_TITLE, VARIABLE_ACTIONS, variableOptions, } from '../constants'; @@ -41,13 +43,6 @@ import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens'; const trackingMixin = Tracking.mixin({ label: EVENT_LABEL }); export default { - modalId: ADD_CI_VARIABLE_MODAL_ID, - tokens: awsTokens, - tokenList: awsTokenList, - awsTipMessage: AWS_TIP_MESSAGE, - containsVariableReferenceMessage: CONTAINS_VARIABLE_REFERENCE_MESSAGE, - environmentScopeLinkTitle: ENVIRONMENT_SCOPE_LINK_TITLE, - expandedVariablesNote: EXPANDED_VARIABLES_NOTE, components: { CiEnvironmentsDropdown, GlAlert, @@ -75,7 +70,6 @@ export default { 'isProtectedByDefault', 'maskedEnvironmentVariablesLink', 'maskableRegex', - 'protectedEnvironmentVariablesLink', ], props: { areScopedVariablesAvailable: { @@ -273,7 +267,20 @@ export default { this.validationErrorEventProperty = ''; }, }, - defaultScope: allEnvironments.text, + i18n: { + awsTipMessage: AWS_TIP_MESSAGE, + containsVariableReferenceMessage: CONTAINS_VARIABLE_REFERENCE_MESSAGE, + defaultScope: allEnvironments.text, + environmentScopeLinkTitle: ENVIRONMENT_SCOPE_LINK_TITLE, + expandedVariablesNote: EXPANDED_VARIABLES_NOTE, + flagsLinkTitle: FLAG_LINK_TITLE, + }, + flagLink: helpPagePath('ci/variables/index', { + anchor: 'define-a-cicd-variable-in-the-ui', + }), + modalId: ADD_CI_VARIABLE_MODAL_ID, + tokens: awsTokens, + tokenList: awsTokenList, variableOptions, }; </script> @@ -340,15 +347,20 @@ export default { data-testid="environment-scope" > <template #label> - {{ __('Environment scope') }} - <gl-link - :title="$options.environmentScopeLinkTitle" - :href="environmentScopeLink" - target="_blank" - data-testid="environment-scope-link" - > - <gl-icon name="question" :size="12" /> - </gl-link> + <div class="gl-display-flex gl-align-items-center"> + <span class="gl-mr-2"> + {{ __('Environment scope') }} + </span> + <gl-link + class="gl-display-flex" + :title="$options.i18n.environmentScopeLinkTitle" + :href="environmentScopeLink" + target="_blank" + data-testid="environment-scope-link" + > + <gl-icon name="question-o" :size="14" /> + </gl-link> + </div> </template> <ci-environments-dropdown v-if="areScopedVariablesAvailable" @@ -358,12 +370,27 @@ export default { @create-environment-scope="createEnvironmentScope" /> - <gl-form-input v-else :value="$options.defaultScope" class="gl-w-full" readonly /> + <gl-form-input v-else :value="$options.i18n.defaultScope" class="gl-w-full" readonly /> </gl-form-group> </template> </div> - <gl-form-group :label="__('Flags')" label-for="ci-variable-flags"> + <gl-form-group> + <template #label> + <div class="gl-display-flex gl-align-items-center"> + <span class="gl-mr-2"> + {{ __('Flags') }} + </span> + <gl-link + class="gl-display-flex" + :title="$options.i18n.flagsLinkTitle" + :href="$options.flagLink" + target="_blank" + > + <gl-icon name="question-o" :size="14" /> + </gl-link> + </div> + </template> <gl-form-checkbox v-model="variable.protected" class="gl-mb-0" @@ -371,9 +398,6 @@ export default { :data-is-protected-checked="variable.protected" > {{ __('Protect variable') }} - <gl-link target="_blank" :href="protectedEnvironmentVariablesLink"> - <gl-icon name="question" :size="12" /> - </gl-link> <p class="gl-mt-2 text-secondary"> {{ __('Export variable to pipelines running on protected branches and tags only.') }} </p> @@ -384,9 +408,6 @@ export default { data-testid="ci-variable-masked-checkbox" > {{ __('Mask variable') }} - <gl-link target="_blank" :href="maskedEnvironmentVariablesLink"> - <gl-icon name="question" :size="12" /> - </gl-link> <p class="gl-mt-2 text-secondary"> {{ __('Variable will be masked in job logs.') }} <span @@ -397,7 +418,7 @@ export default { {{ __('Requires values to meet regular expression requirements.') }}</span > <gl-link target="_blank" :href="maskedEnvironmentVariablesLink">{{ - __('More information') + __('Learn more.') }}</gl-link> </p> </gl-form-checkbox> @@ -408,11 +429,8 @@ export default { @change="setVariableRaw" > {{ __('Expand variable reference') }} - <gl-link target="_blank" :href="containsVariableReferenceLink"> - <gl-icon name="question" :size="12" /> - </gl-link> <p class="gl-mt-2 gl-mb-0 gl-text-secondary"> - <gl-sprintf :message="$options.expandedVariablesNote"> + <gl-sprintf :message="$options.i18n.expandedVariablesNote"> <template #code="{ content }"> <code>{{ content }}</code> </template> @@ -431,7 +449,7 @@ export default { <div class="gl-display-flex gl-flex-direction-row gl-flex-wrap-wrap gl-md-flex-wrap-nowrap"> <div> <p> - <gl-sprintf :message="$options.awsTipMessage"> + <gl-sprintf :message="$options.i18n.awsTipMessage"> <template #deployLink="{ content }"> <gl-link :href="awsTipDeployLink" target="_blank">{{ content }}</gl-link> </template> @@ -467,7 +485,7 @@ export default { variant="warning" data-testid="contains-variable-reference" > - <gl-sprintf :message="$options.containsVariableReferenceMessage"> + <gl-sprintf :message="$options.i18n.containsVariableReferenceMessage"> <template #code="{ content }"> <code>{{ content }}</code> </template> diff --git a/app/assets/javascripts/ci/ci_variable_list/constants.js b/app/assets/javascripts/ci/ci_variable_list/constants.js index 828d0724d93..2e781e3da0c 100644 --- a/app/assets/javascripts/ci/ci_variable_list/constants.js +++ b/app/assets/javascripts/ci/ci_variable_list/constants.js @@ -72,14 +72,14 @@ export const AWS_TOKEN_CONSTANTS = [AWS_ACCESS_KEY_ID, AWS_DEFAULT_REGION, AWS_S export const CONTAINS_VARIABLE_REFERENCE_MESSAGE = __( 'Unselect "Expand variable reference" if you want to use the variable value as a raw string.', ); - +export const DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT = s__( + 'CiVariables|You have reached the maximum number of variables available. To add new variables, you must reduce the number of defined variables.', +); export const ENVIRONMENT_SCOPE_LINK_TITLE = __('Learn more'); export const EXCEEDS_VARIABLE_LIMIT_TEXT = s__( 'CiVariables|This %{entity} has %{currentVariableCount} defined CI/CD variables. The maximum number of variables per %{entity} is %{maxVariableLimit}. To add new variables, you must reduce the number of defined variables.', ); -export const DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT = s__( - 'CiVariables|You have reached the maximum number of variables available. To add new variables, you must reduce the number of defined variables.', -); +export const FLAG_LINK_TITLE = s__('CiVariable|Define a CI/CD variable in the UI'); export const MAXIMUM_VARIABLE_LIMIT_REACHED = s__( 'CiVariables|Maximum number of variables reached.', ); diff --git a/app/assets/javascripts/ci/ci_variable_list/index.js b/app/assets/javascripts/ci/ci_variable_list/index.js index 174a59aba42..afb390746f9 100644 --- a/app/assets/javascripts/ci/ci_variable_list/index.js +++ b/app/assets/javascripts/ci/ci_variable_list/index.js @@ -25,7 +25,6 @@ const mountCiVariableListApp = (containerEl) => { projectFullPath, projectId, protectedByDefault, - protectedEnvironmentVariablesLink, } = containerEl.dataset; const parsedIsProject = parseBoolean(isProject); @@ -66,7 +65,6 @@ const mountCiVariableListApp = (containerEl) => { maskableRegex, projectFullPath, projectId, - protectedEnvironmentVariablesLink, }, render(createElement) { return createElement(component); diff --git a/app/assets/javascripts/ide/components/panes/right.vue b/app/assets/javascripts/ide/components/panes/right.vue index da2d4fbe7f0..8342b3f428c 100644 --- a/app/assets/javascripts/ide/components/panes/right.vue +++ b/app/assets/javascripts/ide/components/panes/right.vue @@ -1,10 +1,9 @@ <script> -import { mapGetters, mapState } from 'vuex'; +import { mapState } from 'vuex'; import { __ } from '~/locale'; import { rightSidebarViews, SIDEBAR_INIT_WIDTH, SIDEBAR_NAV_WIDTH } from '../../constants'; import JobsDetail from '../jobs/detail.vue'; import PipelinesList from '../pipelines/list.vue'; -import Clientside from '../preview/clientside.vue'; import ResizablePanel from '../resizable_panel.vue'; import TerminalView from '../terminal/view.vue'; import CollapsibleSidebar from './collapsible_sidebar.vue'; @@ -20,12 +19,8 @@ export default { }, computed: { ...mapState('terminal', { isTerminalVisible: 'isVisible' }), - ...mapState(['currentMergeRequestId', 'clientsidePreviewEnabled']), - ...mapGetters(['packageJson']), + ...mapState(['currentMergeRequestId']), ...mapState('rightPane', ['isOpen']), - showLivePreview() { - return this.packageJson && this.clientsidePreviewEnabled; - }, rightExtensionTabs() { return [ { @@ -38,12 +33,6 @@ export default { icon: 'rocket', }, { - show: this.showLivePreview, - title: __('Live preview'), - views: [{ component: Clientside, ...rightSidebarViews.clientSidePreview }], - icon: 'live-preview', - }, - { show: this.isTerminalVisible, title: __('Terminal'), views: [{ component: TerminalView, ...rightSidebarViews.terminal }], diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue deleted file mode 100644 index 70b881b6ff6..00000000000 --- a/app/assets/javascripts/ide/components/preview/clientside.vue +++ /dev/null @@ -1,191 +0,0 @@ -<script> -import { GlLoadingIcon } from '@gitlab/ui'; -import { listen } from 'codesandbox-api'; -import { isEmpty, debounce } from 'lodash'; -import { SandpackClient } from '@codesandbox/sandpack-client'; -import { mapActions, mapGetters, mapState } from 'vuex'; -import { - packageJsonPath, - LIVE_PREVIEW_DEBOUNCE, - PING_USAGE_PREVIEW_KEY, - PING_USAGE_PREVIEW_SUCCESS_KEY, -} from '../../constants'; -import eventHub from '../../eventhub'; -import { createPathWithExt } from '../../utils'; -import Navigator from './navigator.vue'; - -export default { - components: { - Navigator, - GlLoadingIcon, - }, - data() { - return { - client: {}, - loading: false, - sandpackReady: false, - }; - }, - computed: { - ...mapState(['entries', 'promotionSvgPath', 'links', 'codesandboxBundlerUrl']), - ...mapGetters(['packageJson', 'currentProject']), - normalizedEntries() { - return Object.keys(this.entries).reduce((acc, path) => { - const file = this.entries[path]; - - if (file.type === 'tree' || !(file.raw || file.content)) return acc; - - return { - ...acc, - [`/${path}`]: { - code: file.content || file.raw, - }, - }; - }, {}); - }, - mainEntry() { - if (!this.packageJson.raw) return false; - - const parsedPackage = JSON.parse(this.packageJson.raw); - - return parsedPackage.main; - }, - showPreview() { - return this.mainEntry && !this.loading; - }, - showEmptyState() { - return !this.mainEntry && !this.loading; - }, - showOpenInCodeSandbox() { - return this.currentProject && this.currentProject.visibility === 'public'; - }, - sandboxOpts() { - return { - files: { ...this.normalizedEntries }, - entry: `/${this.mainEntry}`, - showOpenInCodeSandbox: this.showOpenInCodeSandbox, - }; - }, - }, - watch: { - sandpackReady: { - handler(val) { - if (val) { - this.pingUsage(PING_USAGE_PREVIEW_SUCCESS_KEY); - } - }, - }, - }, - mounted() { - this.onFilesChangeCallback = debounce(() => this.update(), LIVE_PREVIEW_DEBOUNCE); - eventHub.$on('ide.files.change', this.onFilesChangeCallback); - - this.loading = true; - - return this.loadFileContent(packageJsonPath) - .then(() => { - this.loading = false; - }) - .then(() => this.$nextTick()) - .then(() => this.initPreview()); - }, - beforeDestroy() { - // Setting sandpackReady = false protects us form a phantom `update()` being called when `debounce` finishes. - this.sandpackReady = false; - eventHub.$off('ide.files.change', this.onFilesChangeCallback); - - if (!isEmpty(this.client)) { - this.client.cleanup(); - } - - this.client = {}; - - if (this.listener) { - this.listener(); - } - }, - methods: { - ...mapActions(['getFileData', 'getRawFileData']), - ...mapActions('clientside', ['pingUsage']), - loadFileContent(path) { - return this.getFileData({ path, makeFileActive: false }).then(() => - this.getRawFileData({ path }), - ); - }, - initPreview() { - if (!this.mainEntry) return null; - - this.pingUsage(PING_USAGE_PREVIEW_KEY); - - return this.loadFileContent(this.mainEntry) - .then(() => this.$nextTick()) - .then(() => { - this.initClient(); - - this.listener = listen((e) => { - switch (e.type) { - case 'done': - this.sandpackReady = true; - break; - default: - break; - } - }); - }); - }, - update() { - if (!this.sandpackReady) return; - - if (isEmpty(this.client)) { - this.initPreview(); - - return; - } - - this.client.updatePreview(this.sandboxOpts); - }, - initClient() { - const { codesandboxBundlerUrl: bundlerURL } = this; - - const settings = { - fileResolver: { - isFile: (p) => Promise.resolve(Boolean(this.entries[createPathWithExt(p)])), - readFile: (p) => this.loadFileContent(createPathWithExt(p)).then((content) => content), - }, - ...(bundlerURL ? { bundlerURL } : {}), - }; - - this.client = new SandpackClient('#ide-preview', this.sandboxOpts, settings); - }, - }, -}; -</script> - -<template> - <div class="preview h-100 w-100 d-flex flex-column gl-bg-white"> - <template v-if="showPreview"> - <navigator :client="client" /> - <div id="ide-preview"></div> - </template> - <div - v-else-if="showEmptyState" - v-once - class="d-flex h-100 flex-column align-items-center justify-content-center svg-content" - > - <img :src="promotionSvgPath" :alt="s__('IDE|Live Preview')" width="130" height="100" /> - <h3>{{ s__('IDE|Live Preview') }}</h3> - <p class="text-center"> - {{ s__('IDE|Preview your web application using Web IDE client-side evaluation.') }} - </p> - <a - :href="links.webIDEHelpPagePath" - class="btn gl-button btn-confirm" - target="_blank" - rel="noopener noreferrer" - > - {{ s__('IDE|Get started with Live Preview') }} - </a> - </div> - <gl-loading-icon v-else size="lg" class="align-self-center mt-auto mb-auto" /> - </div> -</template> diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue deleted file mode 100644 index 852de16d508..00000000000 --- a/app/assets/javascripts/ide/components/preview/navigator.vue +++ /dev/null @@ -1,136 +0,0 @@ -<script> -import { GlLoadingIcon, GlIcon } from '@gitlab/ui'; -import { listen } from 'codesandbox-api'; - -export default { - components: { - GlIcon, - GlLoadingIcon, - }, - props: { - client: { - type: Object, - required: true, - }, - }, - data() { - return { - currentBrowsingIndex: null, - navigationStack: [], - forwardNavigationStack: [], - path: '', - loading: true, - }; - }, - computed: { - backButtonDisabled() { - return this.navigationStack.length <= 1; - }, - forwardButtonDisabled() { - return !this.forwardNavigationStack.length; - }, - }, - mounted() { - this.listener = listen((e) => { - switch (e.type) { - case 'urlchange': - this.onUrlChange(e); - break; - case 'done': - this.loading = false; - break; - default: - break; - } - }); - }, - beforeDestroy() { - this.listener(); - }, - methods: { - onUrlChange(e) { - const lastPath = this.path; - - this.path = e.url.replace(this.client.bundlerURL, '') || '/'; - - if (lastPath !== this.path) { - this.currentBrowsingIndex = - this.currentBrowsingIndex === null ? 0 : this.currentBrowsingIndex + 1; - this.navigationStack.push(this.path); - } - }, - back() { - const lastPath = this.path; - - this.visitPath(this.navigationStack[this.currentBrowsingIndex - 1]); - - this.forwardNavigationStack.push(lastPath); - - if (this.currentBrowsingIndex === 1) { - this.currentBrowsingIndex = null; - this.navigationStack = []; - } - }, - forward() { - this.visitPath(this.forwardNavigationStack.splice(0, 1)[0]); - }, - refresh() { - this.visitPath(this.path); - }, - visitPath(path) { - // eslint-disable-next-line vue/no-mutating-props - this.client.iframe.src = `${this.client.bundlerURL}${path}`; - }, - }, -}; -</script> - -<template> - <header class="ide-preview-header d-flex align-items-center"> - <button - :aria-label="s__('IDE|Back')" - :disabled="backButtonDisabled" - :class="{ - 'disabled-content': backButtonDisabled, - }" - type="button" - class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent" - @click="back" - > - <gl-icon :size="24" name="chevron-left" class="m-auto" /> - </button> - <button - :aria-label="s__('IDE|Back')" - :disabled="forwardButtonDisabled" - :class="{ - 'disabled-content': forwardButtonDisabled, - }" - type="button" - class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent" - @click="forward" - > - <gl-icon :size="24" name="chevron-right" class="m-auto" /> - </button> - <button - :aria-label="s__('IDE|Refresh preview')" - type="button" - class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent" - @click="refresh" - > - <gl-icon :size="16" name="retry" class="m-auto" /> - </button> - <div class="position-relative w-100 gl-ml-2"> - <input - :value="path || '/'" - type="text" - class="ide-navigator-location form-control bg-white" - readonly - /> - <gl-loading-icon - v-if="loading" - size="sm" - class="position-absolute ide-preview-loading-icon" - /> - </div> - </header> -</template> diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js index 01ce5fa07ee..1aa64656c30 100644 --- a/app/assets/javascripts/ide/constants.js +++ b/app/assets/javascripts/ide/constants.js @@ -64,7 +64,6 @@ export const rightSidebarViews = { pipelines: { name: 'pipelines-list', keepAlive: true }, jobsDetail: { name: 'jobs-detail', keepAlive: false }, mergeRequestInfo: { name: 'merge-request-info', keepAlive: true }, - clientSidePreview: { name: 'clientside', keepAlive: false }, terminal: { name: 'terminal', keepAlive: true }, }; @@ -101,22 +100,13 @@ export const commitActionTypes = { update: 'update', }; -export const packageJsonPath = 'package.json'; - export const SIDE_LEFT = 'left'; export const SIDE_RIGHT = 'right'; -// Live Preview feature -export const LIVE_PREVIEW_DEBOUNCE = 2000; - // This is the maximum number of files to auto open when opening the Web IDE // from a merge request export const MAX_MR_FILES_AUTO_OPEN = 10; export const DEFAULT_BRANCH = 'main'; -// Ping Usage Metrics Keys -export const PING_USAGE_PREVIEW_KEY = 'web_ide_clientside_preview'; -export const PING_USAGE_PREVIEW_SUCCESS_KEY = 'web_ide_clientside_preview_success'; - export const GITLAB_WEB_IDE_FEEDBACK_ISSUE = 'https://gitlab.com/gitlab-org/gitlab/-/issues/377367'; diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js index 1347d92b3b7..29c44d2f596 100644 --- a/app/assets/javascripts/ide/index.js +++ b/app/assets/javascripts/ide/index.js @@ -67,10 +67,8 @@ export const initLegacyWebIDE = (el, options = {}) => { forkInfo: el.dataset.forkInfo ? JSON.parse(el.dataset.forkInfo) : null, }); this.init({ - clientsidePreviewEnabled: parseBoolean(el.dataset.clientsidePreviewEnabled), renderWhitespaceInCode: parseBoolean(el.dataset.renderWhitespaceInCode), editorTheme: window.gon?.user_color_scheme || DEFAULT_THEME, - codesandboxBundlerUrl: el.dataset.codesandboxBundlerUrl, environmentsGuidanceAlertDismissed: !parseBoolean(el.dataset.enableEnvironmentsGuidance), previewMarkdownPath: el.dataset.previewMarkdownPath, userPreferencesPath: el.dataset.userPreferencesPath, diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js index 3c02b1d1da7..c0f666c6652 100644 --- a/app/assets/javascripts/ide/stores/getters.js +++ b/app/assets/javascripts/ide/stores/getters.js @@ -2,7 +2,6 @@ import Api from '~/api'; import { addNumericSuffix } from '~/ide/utils'; import { leftSidebarViews, - packageJsonPath, DEFAULT_PERMISSIONS, PERMISSION_READ_MR, PERMISSION_CREATE_MR, @@ -153,8 +152,6 @@ export const currentBranch = (state, getters) => export const branchName = (_state, getters) => getters.currentBranch && getters.currentBranch.name; -export const packageJson = (state) => state.entries[packageJsonPath]; - export const isOnDefaultBranch = (_state, getters) => getters.currentProject && getters.currentProject.default_branch === getters.branchName; diff --git a/app/assets/javascripts/ide/stores/index.js b/app/assets/javascripts/ide/stores/index.js index b660ff178a2..c2f7126159c 100644 --- a/app/assets/javascripts/ide/stores/index.js +++ b/app/assets/javascripts/ide/stores/index.js @@ -3,7 +3,6 @@ import Vuex from 'vuex'; import * as actions from './actions'; import * as getters from './getters'; import branches from './modules/branches'; -import clientsideModule from './modules/clientside'; import commitModule from './modules/commit'; import editorModule from './modules/editor'; import { setupFileEditorsSync } from './modules/editor/setup'; @@ -29,7 +28,6 @@ export const createStoreOptions = () => ({ branches, fileTemplates: fileTemplates(), rightPane: paneModule(), - clientside: clientsideModule(), router: routerModule, editor: editorModule, }, diff --git a/app/assets/javascripts/ide/stores/modules/clientside/actions.js b/app/assets/javascripts/ide/stores/modules/clientside/actions.js deleted file mode 100644 index 1a8e665867f..00000000000 --- a/app/assets/javascripts/ide/stores/modules/clientside/actions.js +++ /dev/null @@ -1,11 +0,0 @@ -import axios from '~/lib/utils/axios_utils'; - -export const pingUsage = ({ rootGetters }, metricName) => { - const { web_url: projectUrl } = rootGetters.currentProject; - - const url = `${projectUrl}/service_ping/${metricName}`; - - return axios.post(url); -}; - -export default pingUsage; diff --git a/app/assets/javascripts/ide/stores/modules/clientside/index.js b/app/assets/javascripts/ide/stores/modules/clientside/index.js deleted file mode 100644 index b28f7b935a8..00000000000 --- a/app/assets/javascripts/ide/stores/modules/clientside/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import * as actions from './actions'; - -export default () => ({ - namespaced: true, - actions, -}); diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js index b89d9d38a1a..356bbf28a48 100644 --- a/app/assets/javascripts/ide/stores/state.js +++ b/app/assets/javascripts/ide/stores/state.js @@ -26,10 +26,8 @@ export default () => ({ path: '', entry: {}, }, - clientsidePreviewEnabled: false, renderWhitespaceInCode: false, editorTheme: DEFAULT_THEME, - codesandboxBundlerUrl: null, environmentsGuidanceAlertDismissed: false, environmentsGuidanceAlertDetected: false, previewMarkdownPath: '', diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue index 782e8a625a9..6de3f507a39 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue @@ -27,7 +27,7 @@ export default { }, i18n: { signInButtonTextWithSubscriptions: s__('Integrations|Sign in to add namespaces'), - signInText: s__('JiraService|Sign in to GitLab.com to get started.'), + signInText: s__('JiraService|Sign in to GitLab to get started.'), }, GITLAB_COM_BASE_PATH, methods: { diff --git a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js index 5d6e0dff33f..04a82836f69 100644 --- a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js +++ b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js @@ -334,7 +334,7 @@ export const timeToHoursMinutes = (time = '') => { * @param {String} offset An optional Date-compatible offset. * @returns {String} The combined Date's ISO string representation. */ -export const dateAndTimeToISOString = (date, time = '00:00', offset = '') => { +export const dateAndTimeToISOString = (date, time, offset = '') => { const { year, month, day } = dateToYearMonthDate(date); const { hours, minutes } = timeToHoursMinutes(time); const dateString = `${year}-${month}-${day}T${hours}:${minutes}:00.000${offset || 'Z'}`; diff --git a/app/assets/javascripts/super_sidebar/components/create_menu.vue b/app/assets/javascripts/super_sidebar/components/create_menu.vue index 2d2eef19473..e92a6cbf5f5 100644 --- a/app/assets/javascripts/super_sidebar/components/create_menu.vue +++ b/app/assets/javascripts/super_sidebar/components/create_menu.vue @@ -1,13 +1,11 @@ <script> -import { GlDisclosureDropdown, GlTooltipDirective } from '@gitlab/ui'; +import { GlDisclosureDropdown, GlTooltip } from '@gitlab/ui'; import { __ } from '~/locale'; export default { - directives: { - GlTooltip: GlTooltipDirective, - }, components: { GlDisclosureDropdown, + GlTooltip, }, i18n: { createNew: __('Create new...'), @@ -18,17 +16,23 @@ export default { required: true, }, }, + toggleId: 'create-menu-toggle', }; </script> <template> - <gl-disclosure-dropdown - v-gl-tooltip:super-sidebar.bottom="$options.i18n.createNew" - category="tertiary" - icon="plus" - :items="groups" - no-caret - text-sr-only - :toggle-text="$options.i18n.createNew" - /> + <div> + <gl-disclosure-dropdown + category="tertiary" + icon="plus" + :items="groups" + no-caret + text-sr-only + :toggle-text="$options.i18n.createNew" + :toggle-id="$options.toggleId" + /> + <gl-tooltip :target="`#${$options.toggleId}`" placement="bottom" container="#super-sidebar"> + {{ $options.i18n.createNew }} + </gl-tooltip> + </div> </template> diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss index c3688f4a138..2002b4d4dff 100644 --- a/app/assets/stylesheets/page_bundles/ide.scss +++ b/app/assets/stylesheets/page_bundles/ide.scss @@ -906,8 +906,7 @@ $ide-commit-header-height: 48px; padding-bottom: 0; } - .ide-right-sidebar-terminal, - .ide-right-sidebar-clientside { + .ide-right-sidebar-terminal { padding: 0; } } @@ -1083,43 +1082,6 @@ $ide-commit-header-height: 48px; } } -.ide-preview-header { - padding: 0 $grid-size; - border-bottom: 1px solid var(--ide-border-color-alt, $white-dark); - background-color: var(--ide-highlight-background, $gray-light); - min-height: 44px; -} - -.ide-navigator-btn { - height: 24px; - min-width: 24px; - max-width: 24px; - padding: 0; - margin: 0 ($grid-size / 2); - color: var(--ide-text-color-secondary, $gray-600); - - &:first-child { - margin-left: 0; - } -} - -.ide-navigator-location { - padding-top: ($grid-size / 2); - padding-bottom: ($grid-size / 2); - - &:focus { - outline: 0; - box-shadow: none; - border-color: var(--ide-border-color, $gray-100); - } -} - -.ide-preview-loading-icon { - right: $grid-size; - top: 50%; - transform: translateY(-50%); -} - .ide-file-templates { padding: $grid-size $gl-padding; background-color: var(--ide-background, $gray-light); diff --git a/app/controllers/concerns/clientside_preview_csp.rb b/app/controllers/concerns/clientside_preview_csp.rb deleted file mode 100644 index 6892c441b67..00000000000 --- a/app/controllers/concerns/clientside_preview_csp.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -module ClientsidePreviewCSP - extend ActiveSupport::Concern - - included do - content_security_policy do |p| - next if p.directives.blank? - next unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? - - default_frame_src = p.directives['frame-src'] || p.directives['default-src'] - frame_src_values = Array.wrap(default_frame_src) | [Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url].compact - - p.frame_src(*frame_src_values) - end - end -end diff --git a/app/controllers/concerns/record_user_last_activity.rb b/app/controllers/concerns/record_user_last_activity.rb index 6ac87d8f27b..501590d33d9 100644 --- a/app/controllers/concerns/record_user_last_activity.rb +++ b/app/controllers/concerns/record_user_last_activity.rb @@ -20,6 +20,7 @@ module RecordUserLastActivity return if Gitlab::Database.read_only? return unless current_user && current_user.last_activity_on != Date.today - Users::ActivityService.new(current_user).execute + # TODO: add namespace & project - https://gitlab.com/gitlab-org/gitlab/-/issues/387952 + Users::ActivityService.new(author: current_user).execute end end diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 942cb9beed4..2f01bdecd23 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -144,7 +144,8 @@ class GraphqlController < ApplicationController def set_user_last_activity return unless current_user - Users::ActivityService.new(current_user).execute + # TODO: add namespace & project - https://gitlab.com/gitlab-org/gitlab/-/issues/387951 + Users::ActivityService.new(author: current_user).execute end def track_vs_code_usage diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb index bedeae3cf54..d0e14000d8e 100644 --- a/app/controllers/ide_controller.rb +++ b/app/controllers/ide_controller.rb @@ -2,7 +2,6 @@ class IdeController < ApplicationController include VSCodeCDNCSP - include ClientsidePreviewCSP include StaticObjectExternalStorageCSP include Gitlab::Utils::StrongMemoize diff --git a/app/controllers/projects/service_ping_controller.rb b/app/controllers/projects/service_ping_controller.rb index cfc322b47e7..8c16b6b230e 100644 --- a/app/controllers/projects/service_ping_controller.rb +++ b/app/controllers/projects/service_ping_controller.rb @@ -5,24 +5,6 @@ class Projects::ServicePingController < Projects::ApplicationController feature_category :web_ide - def web_ide_clientside_preview - return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? - - Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_count - - head(:ok) - end - - def web_ide_clientside_preview_success - return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? - - Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_success_count - Gitlab::UsageDataCounters::EditorUniqueCounter.track_live_preview_edit_action(author: current_user, - project: project) - - head(:ok) - end - def web_ide_pipelines_count Gitlab::UsageDataCounters::WebIdeCounter.increment_pipelines_count diff --git a/app/controllers/repositories/git_http_controller.rb b/app/controllers/repositories/git_http_controller.rb index 144ec4c0de9..bd3461d8331 100644 --- a/app/controllers/repositories/git_http_controller.rb +++ b/app/controllers/repositories/git_http_controller.rb @@ -116,7 +116,7 @@ module Repositories end def log_user_activity - Users::ActivityService.new(user).execute + Users::ActivityService.new(author: user, project: project, namespace: project&.namespace).execute end end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 699dcf1adac..b6aba04c877 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -289,7 +289,7 @@ class SessionsController < Devise::SessionsController def log_user_activity(user) login_counter.increment - Users::ActivityService.new(user).execute + Users::ActivityService.new(author: user).execute end def load_recaptcha diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 1b7657c0381..40c5967723c 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -384,7 +384,6 @@ module ApplicationSettingsHelper :user_default_internal_regex, :user_oauth_applications, :version_check_enabled, - :web_ide_clientside_preview_enabled, :diff_max_patch_bytes, :diff_max_files, :diff_max_lines, diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb index 0e81cea8ac7..02980ec422e 100644 --- a/app/helpers/ide_helper.rb +++ b/app/helpers/ide_helper.rb @@ -43,9 +43,7 @@ module IdeHelper 'promotion-svg-path': image_path('illustrations/web-ide_promotion.svg'), 'ci-help-page-path' => help_page_path('ci/quick_start/index'), 'web-ide-help-page-path' => help_page_path('user/project/web_ide/index.md'), - 'clientside-preview-enabled': Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?.to_s, 'render-whitespace-in-code': current_user.render_whitespace_in_code.to_s, - 'codesandbox-bundler-url': Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url, 'default-branch' => @project && @project.default_branch, 'project' => convert_to_project_entity_json(@project), 'enable-environments-guidance' => enable_environments_guidance?.to_s, diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index ebf8e3d54bf..d58136717b9 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -12,6 +12,7 @@ class ApplicationSetting < ApplicationRecord ignore_columns %i[static_objects_external_storage_auth_token], remove_with: '14.9', remove_after: '2022-03-22' ignore_column :user_email_lookup_limit, remove_with: '15.0', remove_after: '2022-04-18' ignore_column :send_user_confirmation_email, remove_with: '15.8', remove_after: '2022-12-18' + ignore_column :web_ide_clientside_preview_enabled, remove_with: '15.11', remove_after: '2023-04-22' INSTANCE_REVIEW_MIN_USERS = 50 GRAFANA_URL_ERROR_MESSAGE = 'Please check your Grafana URL setting in ' \ diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index e60a54fa745..f13b2143cd3 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -523,12 +523,6 @@ module ApplicationSettingImplementation static_objects_external_storage_url.present? end - # This will eventually be configurable - # https://gitlab.com/gitlab-org/gitlab/issues/208161 - def web_ide_clientside_preview_bundler_url - 'https://sandbox-prod.gitlab-static.net' - end - def ensure_key_restrictions! return if Gitlab::Database.read_only? return unless Gitlab::FIPS.enabled? diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb index bf4a26400e1..acc5176059d 100644 --- a/app/services/event_create_service.rb +++ b/app/services/event_create_service.rb @@ -245,7 +245,7 @@ class EventCreateService Users::LastPushEventService.new(current_user) .cache_last_push_event(event) - Users::ActivityService.new(current_user).execute + Users::ActivityService.new(author: current_user, namespace: namespace, project: project).execute end def create_event(resource_parent, current_user, status, attributes = {}) diff --git a/app/services/users/activity_service.rb b/app/services/users/activity_service.rb index 4978f778870..c8f9c28061f 100644 --- a/app/services/users/activity_service.rb +++ b/app/services/users/activity_service.rb @@ -4,38 +4,56 @@ module Users class ActivityService LEASE_TIMEOUT = 1.minute.to_i - def initialize(author) + def initialize(author:, namespace: nil, project: nil) @user = if author.respond_to?(:username) author elsif author.respond_to?(:user) author.user end - @user = nil unless @user.is_a?(User) + @user = nil unless user.is_a?(User) + @namespace = namespace + @project = project end def execute - return unless @user + return unless user ::Gitlab::Database::LoadBalancing::Session.without_sticky_writes { record_activity } end private + attr_reader :user, :namespace, :project + def record_activity return if Gitlab::Database.read_only? today = Date.today - return if @user.last_activity_on == today + return if user.last_activity_on == today - lease = Gitlab::ExclusiveLease.new("activity_service:#{@user.id}", + lease = Gitlab::ExclusiveLease.new("activity_service:#{user.id}", timeout: LEASE_TIMEOUT) return unless lease.try_obtain - @user.update_attribute(:last_activity_on, today) + user.update_attribute(:last_activity_on, today) + + Gitlab::UsageDataCounters::HLLRedisCounter.track_event('unique_active_user', values: user.id) + + return unless Feature.enabled?(:route_hll_to_snowplow_phase3) - Gitlab::UsageDataCounters::HLLRedisCounter.track_event('unique_active_user', values: @user.id) + Gitlab::Tracking.event( + 'Users::ActivityService', + 'perform_action', + user: user, + namespace: namespace, + project: project, + label: 'redis_hll_counters.manage.unique_active_users_monthly', + context: [ + Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: 'unique_active_user').to_context + ] + ) end end end diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml index dceee07019c..e9df82a922b 100644 --- a/app/views/admin/application_settings/general.html.haml +++ b/app/views/admin/application_settings/general.html.haml @@ -89,26 +89,6 @@ .settings-content = render 'terminal' -%section.settings.no-animate#js-web-ide-settings{ class: ('expanded' if expanded_by_default?) } - .settings-header - %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only - = _('Web IDE') - = render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do - = expanded_by_default? ? _('Collapse') : _('Expand') - %p - = _('Manage Web IDE features.') - .settings-content - = gitlab_ui_form_for @application_setting, url: general_admin_application_settings_path(anchor: "js-web-ide-settings"), html: { class: 'fieldset-form', id: 'web-ide-settings' } do |f| - = form_errors(@application_setting) - - %fieldset - .form-group - - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('user/project/web_ide/index', anchor: 'enable-live-preview') } - = f.gitlab_ui_checkbox_component :web_ide_clientside_preview_enabled, - s_('IDE|Live Preview'), - help_text: s_('Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} ').html_safe % { link_start: link_start, link_end: '</a>'.html_safe } - = f.submit _('Save changes'), pajamas_button: true - = render_if_exists 'admin/application_settings/maintenance_mode_settings_form' = render 'admin/application_settings/gitpod' = render 'admin/application_settings/kroki' diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml index af98025d257..be4fa19019f 100644 --- a/app/views/ci/variables/_index.html.haml +++ b/app/views/ci/variables/_index.html.haml @@ -24,7 +24,6 @@ aws_tip_commands_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'use-an-image-to-run-aws-commands'), aws_tip_learn_link: help_page_path('ci/cloud_deployment/index.md'), contains_variable_reference_link: help_page_path('ci/variables/index', anchor: 'prevent-cicd-variable-expansion'), - protected_environment_variables_link: help_page_path('ci/variables/index', anchor: 'protect-a-cicd-variable'), masked_environment_variables_link: help_page_path('ci/variables/index', anchor: 'mask-a-cicd-variable'), environment_scope_link: help_page_path('ci/environments/index', anchor: 'limit-the-environment-scope-of-a-cicd-variable') } } diff --git a/config/events/1671713111_Users__ActivityService_perform_action.yml b/config/events/1671713111_Users__ActivityService_perform_action.yml new file mode 100644 index 00000000000..4b1f90d42b4 --- /dev/null +++ b/config/events/1671713111_Users__ActivityService_perform_action.yml @@ -0,0 +1,23 @@ +--- +description: User's last_activity_on gets updated +category: Users::ActivityService +action: perform_action +label_description: key_path of Service Ping metric redis_hll_counters.manage.unique_active_users_monthly +property_description: +value_description: +extra_properties: +identifiers: +product_section: dev +product_stage: manage +product_group: manage +product_category: +milestone: "15.8" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108108 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/routes/project.rb b/config/routes/project.rb index eb7950694aa..4a2f8375249 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -590,8 +590,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do end scope :service_ping, controller: :service_ping do - post :web_ide_clientside_preview # rubocop:todo Cop/PutProjectRoutesUnderScope - post :web_ide_clientside_preview_success # rubocop:todo Cop/PutProjectRoutesUnderScope post :web_ide_pipelines_count # rubocop:todo Cop/PutProjectRoutesUnderScope end diff --git a/data/deprecations/16-0-post-ci-lint.yml b/data/deprecations/16-0-post-ci-lint.yml index 42c9d29a3d5..407b0124a83 100644 --- a/data/deprecations/16-0-post-ci-lint.yml +++ b/data/deprecations/16-0-post-ci-lint.yml @@ -24,7 +24,7 @@ stage: verify # (required) String value of the stage that the feature was created in. e.g., Growth issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/381669 # (required) Link to the deprecation issue in GitLab body: | # (required) Do not modify this line, instead modify the lines below. - The `POST ci/lint` API endpoint is deprecated in 15.7, and will be removed in 16.0. This endpoint does not validate the full range of CI/CD configuration options. Instead, use [`POST /projects/:id/ci/lint`](https://docs.gitlab.com/15.5/ee/api/lint.html#validate-a-ci-yaml-configuration-with-a-namespace), which properly validates CI/CD configuration. + The `POST ci/lint` API endpoint is deprecated in 15.7, and will be removed in 16.0. This endpoint does not validate the full range of CI/CD configuration options. Instead, use [`POST /projects/:id/ci/lint`](https://docs.gitlab.com/ee/api/lint.html#validate-a-ci-yaml-configuration-with-a-namespace), which properly validates CI/CD configuration. # # OPTIONAL END OF SUPPORT FIELDS # diff --git a/db/migrate/20230124122143_add_deploy_key_id_to_create_access_levels.rb b/db/migrate/20230124122143_add_deploy_key_id_to_create_access_levels.rb new file mode 100644 index 00000000000..d26cf2a1e5f --- /dev/null +++ b/db/migrate/20230124122143_add_deploy_key_id_to_create_access_levels.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddDeployKeyIdToCreateAccessLevels < Gitlab::Database::Migration[2.1] + def up + add_column :protected_tag_create_access_levels, :deploy_key_id, :integer + end + + def down + remove_column :protected_tag_create_access_levels, :deploy_key_id + end +end diff --git a/db/migrate/20230124193917_add_index_for_protected_tag_create_access_levels.rb b/db/migrate/20230124193917_add_index_for_protected_tag_create_access_levels.rb new file mode 100644 index 00000000000..7068f4f0447 --- /dev/null +++ b/db/migrate/20230124193917_add_index_for_protected_tag_create_access_levels.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AddIndexForProtectedTagCreateAccessLevels < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + DEPLOY_KEY_INDEX_NAME = 'index_protected_tag_create_access_levels_on_deploy_key_id' + + def up + add_concurrent_foreign_key :protected_tag_create_access_levels, :keys, column: :deploy_key_id, on_delete: :cascade + add_concurrent_index :protected_tag_create_access_levels, :deploy_key_id, + name: DEPLOY_KEY_INDEX_NAME + end + + def down + remove_foreign_key_if_exists :protected_tag_create_access_levels, column: :deploy_key_id + remove_concurrent_index_by_name :protected_tag_create_access_levels, name: DEPLOY_KEY_INDEX_NAME + end +end diff --git a/db/schema_migrations/20230124122143 b/db/schema_migrations/20230124122143 new file mode 100644 index 00000000000..a38e5b7c40b --- /dev/null +++ b/db/schema_migrations/20230124122143 @@ -0,0 +1 @@ +be87eb6052d3f853f05f59a6deb8669857047ca95d28b209b1c19c66fa96ff15
\ No newline at end of file diff --git a/db/schema_migrations/20230124193917 b/db/schema_migrations/20230124193917 new file mode 100644 index 00000000000..b8e45dd4692 --- /dev/null +++ b/db/schema_migrations/20230124193917 @@ -0,0 +1 @@ +277c1abd9cc4f9fb6aca4991b7643d8b9964ef466f4d209848c90b34c8eec9c0
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 8d187d6798e..eedf798f980 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -21005,7 +21005,8 @@ CREATE TABLE protected_tag_create_access_levels ( user_id integer, group_id integer, created_at timestamp without time zone NOT NULL, - updated_at timestamp without time zone NOT NULL + updated_at timestamp without time zone NOT NULL, + deploy_key_id integer ); CREATE SEQUENCE protected_tag_create_access_levels_id_seq @@ -31069,6 +31070,8 @@ CREATE UNIQUE INDEX index_protected_environments_on_project_id_and_name ON prote CREATE INDEX index_protected_tag_create_access ON protected_tag_create_access_levels USING btree (protected_tag_id); +CREATE INDEX index_protected_tag_create_access_levels_on_deploy_key_id ON protected_tag_create_access_levels USING btree (deploy_key_id); + CREATE INDEX index_protected_tag_create_access_levels_on_group_id ON protected_tag_create_access_levels USING btree (group_id); CREATE INDEX index_protected_tag_create_access_levels_on_user_id ON protected_tag_create_access_levels USING btree (user_id); @@ -33597,6 +33600,9 @@ ALTER TABLE ONLY sprints ALTER TABLE ONLY push_event_payloads ADD CONSTRAINT fk_36c74129da FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE; +ALTER TABLE ONLY protected_tag_create_access_levels + ADD CONSTRAINT fk_386a642e13 FOREIGN KEY (deploy_key_id) REFERENCES keys(id) ON DELETE CASCADE; + ALTER TABLE ONLY incident_management_timeline_events ADD CONSTRAINT fk_38a74279df FOREIGN KEY (updated_by_user_id) REFERENCES users(id) ON DELETE SET NULL; diff --git a/doc/administration/auth/atlassian.md b/doc/administration/auth/atlassian.md index b02ac06b67f..58412078802 100644 --- a/doc/administration/auth/atlassian.md +++ b/doc/administration/auth/atlassian.md @@ -41,7 +41,10 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu sudo -u git -H editor /home/git/gitlab/config/gitlab.yml ``` -1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings to enable single sign-on and add `atlassian_oauth2` as an OAuth provider. +1. Edit the [common configuration file settings](../../integration/omniauth.md#configure-common-settings) + to add `atlassian_oauth2` as a single sign-on provider. This enables + Just-In-Time account provisioning for users who do not have an existing + GitLab account. 1. Add the provider configuration for Atlassian: For Omnibus GitLab installations: diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md index d51601439f9..4eabdddfc63 100644 --- a/doc/administration/auth/authentiq.md +++ b/doc/administration/auth/authentiq.md @@ -27,7 +27,9 @@ Authentiq generates a Client ID and the accompanying Client Secret for you to us sudo -u git -H editor /home/git/gitlab/config/gitlab.yml ``` -1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings to enable single sign-on and add Authentiq as an OAuth provider. +1. Edit the [common configuration file settings](../../integration/omniauth.md#configure-common-settings) + to add `authentiq` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration for Authentiq: diff --git a/doc/administration/auth/cognito.md b/doc/administration/auth/cognito.md index d12797b5359..aefc00fba82 100644 --- a/doc/administration/auth/cognito.md +++ b/doc/administration/auth/cognito.md @@ -41,7 +41,9 @@ To enable AWS Cognito as an authentication provider, complete the following step ## Configure GitLab -1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](../../integration/omniauth.md#configure-common-settings) + to add `cognito` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. On your GitLab server, open the configuration file. **For Omnibus installations** @@ -95,4 +97,4 @@ Select this option to begin the authentication process. AWS Cognito then asks you to sign in and authorize the GitLab application. If the authorization is successful, you're redirected and signed in to your GitLab instance. -For more information, see [Configure initial settings](../../integration/omniauth.md#configure-initial-settings). +For more information, see [Configure common settings](../../integration/omniauth.md#configure-common-settings). diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md index 4395309e91e..277e59b1a8a 100644 --- a/doc/administration/auth/crowd.md +++ b/doc/administration/auth/crowd.md @@ -40,8 +40,9 @@ this provider also allows Crowd authentication for Git-over-https requests. sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) - for initial settings. +1. Edit the [common configuration file settings](../../integration/omniauth.md#configure-common-settings) + to add `crowd` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration: diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md index c1e76d1c2ed..8c9800aa792 100644 --- a/doc/administration/auth/jwt.md +++ b/doc/administration/auth/jwt.md @@ -25,7 +25,9 @@ JWT provides you with a secret key for you to use. sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](../../integration/omniauth.md#configure-common-settings) + to add `jwt` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration. For Omnibus GitLab: diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md index 6ec00156021..08919b6b026 100644 --- a/doc/administration/auth/oidc.md +++ b/doc/administration/auth/oidc.md @@ -29,7 +29,9 @@ The OpenID Connect provides you with a client's details and secret for you to us sudo -u git -H editor config/gitlab.yml ``` -1. [Configure initial settings](../../integration/omniauth.md#configure-initial-settings). +1. Edit the [common configuration file settings](../../integration/omniauth.md#configure-common-settings) + to add `openid_connect` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration. @@ -254,7 +256,7 @@ Azure B2C [offers two ways of defining the business logic for logging in a user] Custom policies are required because standard Azure B2C user flows [do not send the OpenID `email` claim](https://github.com/MicrosoftDocs/azure-docs/issues/16566). Therefore, the standard user flows do not work with the -[`allow_single_sign_on` or `auto_link_user` parameters](../../integration/omniauth.md#configure-initial-settings). +[`allow_single_sign_on` or `auto_link_user` parameters](../../integration/omniauth.md#configure-common-settings). With a standard Azure B2C policy, GitLab cannot create a new account or link to an existing account with an email address. diff --git a/doc/api/settings.md b/doc/api/settings.md index 6d92ceec285..74dcf5b8fda 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -522,7 +522,6 @@ listed in the descriptions of the relevant settings. | `user_show_add_ssh_key_message` | boolean | no | When set to `false` disable the `You won't be able to pull or push project code via SSH` warning shown to users with no uploaded SSH key. | | `version_check_enabled` | boolean | no | Let GitLab inform you when an update is available. | | `whats_new_variant` | string | no | What's new variant, possible values: `all_tiers`, `current_tier`, and `disabled`. | -| `web_ide_clientside_preview_enabled` | boolean | no | Live Preview (allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview). | | `wiki_page_max_content_bytes` | integer | no | Maximum wiki page content size in **bytes**. Default: 52428800 Bytes (50 MB). The minimum value is 1024 bytes. | | `jira_connect_application_key` | String | no | Application ID of the OAuth application that should be used to authenticate with the GitLab for Jira Cloud app | | `jira_connect_proxy_url` | String | no | URL of the GitLab instance that should be used as a proxy for the GitLab for Jira Cloud app | diff --git a/doc/architecture/blueprints/remote_development/index.md b/doc/architecture/blueprints/remote_development/index.md index 38c3782f5e3..162ae04f6b6 100644 --- a/doc/architecture/blueprints/remote_development/index.md +++ b/doc/architecture/blueprints/remote_development/index.md @@ -76,7 +76,7 @@ The current production [Web IDE](../../../user/project/web_ide/index.md). An advanced editor with commit staging that currently supports: -- [Live Preview](../../../user/project/web_ide/index.md#live-preview) +- [Live Preview](../../../user/project/web_ide/index.md#live-preview-removed) - [Interactive Web Terminals](../../../user/project/web_ide/index.md#interactive-web-terminals-for-the-web-ide) ### Web IDE diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md index 46683053510..7813a8b5d02 100644 --- a/doc/ci/environments/index.md +++ b/doc/ci/environments/index.md @@ -200,10 +200,8 @@ associated with your project, you can configure these deployments from your `.gitlab-ci.yml` file. NOTE: -Kubernetes configuration isn't supported for Kubernetes clusters that are +Kubernetes configuration isn't supported for Kubernetes clusters [managed by GitLab](../../user/project/clusters/gitlab_managed_clusters.md). -To follow progress on support for GitLab-managed clusters, see the -[relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/38054). The following configuration options are supported: diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index 6165cce9d46..a51fbd6188d 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -1780,9 +1780,7 @@ environment, using the `production` **Additional details**: - Kubernetes configuration is not supported for Kubernetes clusters - that are [managed by GitLab](../../user/project/clusters/gitlab_managed_clusters.md). - To follow progress on support for GitLab-managed clusters, see the - [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/38054). + [managed by GitLab](../../user/project/clusters/gitlab_managed_clusters.md). **Related topics**: diff --git a/doc/development/integrations/codesandbox.md b/doc/development/integrations/codesandbox.md index b7fe3fbd1c4..4553ed2966f 100644 --- a/doc/development/integrations/codesandbox.md +++ b/doc/development/integrations/codesandbox.md @@ -2,12 +2,17 @@ stage: none group: Development info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +remove_date: '2023-02-01' --- -# Set up local CodeSandbox development environment +# Set up local CodeSandbox development environment (removed) + +WARNING: +This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108627) in GitLab 15.8 +and is planned for removal in 15.9. This change is a breaking change. This guide walks through setting up a local [CodeSandbox repository](https://github.com/codesandbox/codesandbox-client) and integrating it with a local GitLab instance. CodeSandbox -is used to power the Web IDE [Live Preview feature](../../user/project/web_ide/index.md#live-preview). Having a local CodeSandbox setup is useful for debugging upstream issues or +is used to power the Web IDE [Live Preview feature](../../user/project/web_ide/index.md#live-preview-removed). Having a local CodeSandbox setup is useful for debugging upstream issues or creating upstream contributions like [this one](https://github.com/codesandbox/codesandbox-client/pull/5137). ## Initial setup @@ -114,7 +119,11 @@ out of the box: npx http-server --proxy http://localhost:3000 -S -C $PATH_TO_CERT_PEM -K $PATH_TO_KEY_PEM -p 8044 -d false ``` -### Update `bundler_url` setting in GitLab +### Update `bundler_url` setting in GitLab (removed) + +WARNING: +This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108627) in GitLab 15.8 +and is planned for removal in 15.9. This change is a breaking change. We need to update our `application_setting_implementation.rb` to point to the server that hosts the CodeSandbox `sandpack` assets. For instance, if these assets are hosted by a server at `https://sandpack.local:8044`: diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md index 40bb03cb5b4..14c9cb33446 100644 --- a/doc/development/service_ping/index.md +++ b/doc/development/service_ping/index.md @@ -210,7 +210,6 @@ The following is example content of the Service Ping payload. "prometheus_metrics_enabled": false, "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com", "signup_enabled": true, - "web_ide_clientside_preview_enabled": true, "projects_with_expiration_policy_disabled": 999, "projects_with_expiration_policy_enabled": 999, ... diff --git a/doc/integration/alicloud.md b/doc/integration/alicloud.md index 263b3837d1d..d861d32e96a 100644 --- a/doc/integration/alicloud.md +++ b/doc/integration/alicloud.md @@ -59,7 +59,9 @@ Sign in to the AliCloud platform and create an application on it. AliCloud gener sudo -u git -H editor config/gitlab.yml ``` -1. [Configure the initial settings](omniauth.md#configure-initial-settings). +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `alicloud` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration. Replace `YOUR_APP_ID` with the ID on the application details page and `YOUR_APP_SECRET` with the **SecretValue** you got when you registered the AliCloud application. diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md index 448807e91fc..ad20057f452 100644 --- a/doc/integration/auth0.md +++ b/doc/integration/auth0.md @@ -42,8 +42,9 @@ application. sudo -u git -H editor config/gitlab.yml ``` -1. Read [Configure initial settings](omniauth.md#configure-initial-settings) - for initial settings. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `auth0` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration: diff --git a/doc/integration/azure.md b/doc/integration/azure.md index 8c30a0cef77..cc479dbf65d 100644 --- a/doc/integration/azure.md +++ b/doc/integration/azure.md @@ -68,7 +68,9 @@ Alternatively, add the `User.Read.All` application permission. sudo -u git -H editor config/gitlab.yml ``` -1. [Configure the initial settings](omniauth.md#configure-initial-settings). +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `azure_oauth2` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration. Replace `<client_id>`, `<client_secret>`, and `<tenant_id>` with the values you got when you registered the Azure application. diff --git a/doc/integration/cas.md b/doc/integration/cas.md index 35c5a6db4a7..750c9aeb8a4 100644 --- a/doc/integration/cas.md +++ b/doc/integration/cas.md @@ -32,7 +32,9 @@ configure CAS for back-channel logout. sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `cas3` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration: diff --git a/doc/integration/ding_talk.md b/doc/integration/ding_talk.md index 18423fa1607..ca939dc9f9a 100644 --- a/doc/integration/ding_talk.md +++ b/doc/integration/ding_talk.md @@ -51,7 +51,9 @@ Sign in to DingTalk Open Platform and create an application on it. DingTalk gene sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `dingtalk` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration: diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md index 7c6afffc847..8b7bdeaa177 100644 --- a/doc/integration/facebook.md +++ b/doc/integration/facebook.md @@ -72,7 +72,9 @@ Facebook. Facebook generates an app ID and secret key for you to use. sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `facebook` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration: diff --git a/doc/integration/github.md b/doc/integration/github.md index 6b59128966a..8f60e1b5d71 100644 --- a/doc/integration/github.md +++ b/doc/integration/github.md @@ -35,7 +35,9 @@ your website could enable the covert redirect attack. ## Enable GitHub OAuth in GitLab -1. [Configure the initial settings](omniauth.md#configure-initial-settings) in GitLab. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `github` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Edit the GitLab configuration file using the following information: diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md index 0ee5b70c958..44dba2b1829 100644 --- a/doc/integration/gitlab.md +++ b/doc/integration/gitlab.md @@ -51,7 +51,9 @@ GitLab.com generates an application ID and secret key for you to use. sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `gitlab` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration: For Omnibus installations authenticating against **GitLab.com**: diff --git a/doc/integration/google.md b/doc/integration/google.md index 947bf0303be..5eac639f119 100644 --- a/doc/integration/google.md +++ b/doc/integration/google.md @@ -71,7 +71,9 @@ On your GitLab server: sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `google_oauth2` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration: For Omnibus GitLab: diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md index 2125aea892b..a518349b1ad 100644 --- a/doc/integration/kerberos.md +++ b/doc/integration/kerberos.md @@ -99,9 +99,9 @@ to authenticate with Kerberos tokens. #### Enable single sign-on -See [Configure initial settings](omniauth.md#configure-initial-settings) -for initial settings to enable single sign-on and add Kerberos servers -as an identity provider. +Edit the [common configuration file settings](omniauth.md#configure-common-settings) +to add `kerberos` as a single sign-on provider. This enables Just-In-Time +account provisioning for users who do not have an existing GitLab account. ## Create and link Kerberos accounts @@ -138,7 +138,8 @@ with your Kerberos credentials. The first time users sign in to GitLab with their Kerberos accounts, GitLab creates a matching account. -Before you continue, review the [Configure initial settings](omniauth.md#configure-initial-settings) options in Omnibus and GitLab source. You must also include `kerberos`. +Before you continue, review the [common configuration settings](omniauth.md#configure-common-settings) +options in Omnibus and GitLab source. You must also include `kerberos`. With that information at hand: diff --git a/doc/integration/oauth2_generic.md b/doc/integration/oauth2_generic.md index c51400113d4..2c0439a328c 100644 --- a/doc/integration/oauth2_generic.md +++ b/doc/integration/oauth2_generic.md @@ -54,7 +54,9 @@ To configure the provider: :::TabTitle Linux package (Omnibus) - 1. [Configure the initial settings](omniauth.md#configure-initial-settings). + 1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `oauth2_generic` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Edit `/etc/gitlab/gitlab.rb` to add the configuration for your provider. For example: ```ruby @@ -96,7 +98,9 @@ To configure the provider: :::TabTitle Helm chart (Kubernetes) - 1. [Configure the initial settings](omniauth.md#configure-initial-settings). + 1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `oauth2_generic` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Export the Helm values: ```shell @@ -146,7 +150,9 @@ To configure the provider: :::TabTitle Self-compiled (source) - 1. [Configure the initial settings](omniauth.md#configure-initial-settings). + 1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `oauth2_generic` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Edit `/home/git/gitlab/config/gitlab.yml`: ```yaml diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md index 2dd8505b558..07dbe46691b 100644 --- a/doc/integration/omniauth.md +++ b/doc/integration/omniauth.md @@ -38,7 +38,7 @@ GitLab supports the following OmniAuth providers. | [SAML](saml.md) | `saml` | | [Twitter](twitter.md) | `twitter` | -## Initial settings +## Configure common settings Before you configure the OmniAuth provider, configure the settings that are common for all providers. @@ -503,7 +503,7 @@ There are two methods to update the `extern_uid`: Identity.where(extern_uid: 'old-id').update!(extern_uid: 'new-id')` ``` -## Limitations +## Known issues Most supported OmniAuth providers don't support Git over HTTP password authentication. As a workaround, you can authenticate using a [personal access token](../user/profile/personal_access_tokens.md). diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md index d4d2bfacb4f..16432d3ca5d 100644 --- a/doc/integration/salesforce.md +++ b/doc/integration/salesforce.md @@ -48,7 +48,9 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `salesforce` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration: diff --git a/doc/integration/saml.md b/doc/integration/saml.md index a6840b50e27..b210a9b9888 100644 --- a/doc/integration/saml.md +++ b/doc/integration/saml.md @@ -41,7 +41,9 @@ For more information on: sudo -u git -H editor config/gitlab.yml ``` -1. Edit the initial [configuration settings](omniauth.md#configure-initial-settings). +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `saml` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. To allow your users to use SAML to sign up without having to manually create an account first, add the following values to your configuration. diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md index 90fb63ff40a..f1bfc5a3662 100644 --- a/doc/integration/twitter.md +++ b/doc/integration/twitter.md @@ -62,7 +62,9 @@ Twitter. Twitter generates a client ID and secret key for you to use. sudo -u git -H editor config/gitlab.yml ``` -1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings. +1. Edit the [common configuration file settings](omniauth.md#configure-common-settings) + to add `twitter` as a single sign-on provider. This enables Just-In-Time + account provisioning for users who do not have an existing GitLab account. 1. Add the provider configuration. diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index e3d6630c85b..41387c655c0 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -129,7 +129,7 @@ GitLab has several features which can help you manage the number of users: - Enable the [**Require administrator approval for new sign ups**](../../user/admin_area/settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups) option. -- Enable `block_auto_created_users` for new sign-ups via [LDAP](../../administration/auth/ldap/index.md#basic-configuration-settings) or [OmniAuth](../../integration/omniauth.md#configure-initial-settings). +- Enable `block_auto_created_users` for new sign-ups via [LDAP](../../administration/auth/ldap/index.md#basic-configuration-settings) or [OmniAuth](../../integration/omniauth.md#configure-common-settings). - Enable the [User cap](../../user/admin_area/settings/sign_up_restrictions.md#user-cap) option. **Available in GitLab 13.7 and later**. - [Disable new sign-ups](../../user/admin_area/settings/sign_up_restrictions.md), and instead manage new diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md index 763b82f9010..5b3679544c3 100644 --- a/doc/update/deprecations.md +++ b/doc/update/deprecations.md @@ -836,7 +836,7 @@ WARNING: This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/). Review the details carefully before upgrading. -The `POST ci/lint` API endpoint is deprecated in 15.7, and will be removed in 16.0. This endpoint does not validate the full range of CI/CD configuration options. Instead, use [`POST /projects/:id/ci/lint`](https://docs.gitlab.com/15.5/ee/api/lint.html#validate-a-ci-yaml-configuration-with-a-namespace), which properly validates CI/CD configuration. +The `POST ci/lint` API endpoint is deprecated in 15.7, and will be removed in 16.0. This endpoint does not validate the full range of CI/CD configuration options. Instead, use [`POST /projects/:id/ci/lint`](https://docs.gitlab.com/ee/api/lint.html#validate-a-ci-yaml-configuration-with-a-namespace), which properly validates CI/CD configuration. </div> </div> diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md index cdffce8abe2..222f439176d 100644 --- a/doc/user/admin_area/moderate_users.md +++ b/doc/user/admin_area/moderate_users.md @@ -17,7 +17,7 @@ pending approval state because an administrator has enabled any of the following - [Require administrator approval for new sign-ups](settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups) setting. - [User cap](settings/sign_up_restrictions.md#user-cap). -- [Block auto-created users (OmniAuth)](../../integration/omniauth.md#configure-initial-settings) +- [Block auto-created users (OmniAuth)](../../integration/omniauth.md#configure-common-settings) - [Block auto-created users (LDAP)](../../administration/auth/ldap/index.md#basic-configuration-settings) When a user registers for an account while this setting is enabled: diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md index b2b702bde7c..2b5c3b5ee21 100644 --- a/doc/user/admin_area/settings/index.md +++ b/doc/user/admin_area/settings/index.md @@ -49,7 +49,6 @@ The **General** settings contain: - [External Authentication](external_authorization.md#configuration) - External Classification Policy Authorization. - [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) - Set max session time for web terminal. -- [Web IDE](../../project/web_ide/index.md#enable-live-preview) - Manage Web IDE features. - [FLoC](floc.md) - Enable or disable [Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) tracking. diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md index 9f1d4eea851..c44901b1ad7 100644 --- a/doc/user/admin_area/settings/sign_up_restrictions.md +++ b/doc/user/admin_area/settings/sign_up_restrictions.md @@ -48,7 +48,7 @@ automatically approved in a background job. NOTE: This setting doesn't apply to LDAP or OmniAuth users. To enforce approvals for new users signing up using OmniAuth or LDAP, set `block_auto_created_users` to `true` in the -[OmniAuth configuration](../../../integration/omniauth.md#configure-initial-settings) or +[OmniAuth configuration](../../../integration/omniauth.md#configure-common-settings) or [LDAP configuration](../../../administration/auth/ldap/index.md#basic-configuration-settings). ## Require email confirmation diff --git a/doc/user/clusters/cost_management.md b/doc/user/clusters/cost_management.md index 75bc9e23c0f..3d5641c8ceb 100644 --- a/doc/user/clusters/cost_management.md +++ b/doc/user/clusters/cost_management.md @@ -19,7 +19,7 @@ On self-managed GitLab, by default this feature is not available. To make it ava Cluster cost management provides insights into cluster resource usage. GitLab provides an example [`kubecost-cost-model`](https://gitlab.com/gitlab-examples/kubecost-cost-model/) project that uses the GitLab Prometheus integration and -[Kubecost's `cost-model`](https://github.com/kubecost/cost-model) to provide cluster cost +[OpenCost `cost-model`](https://github.com/opencost/opencost) to provide cluster cost insights within GitLab: ![Example dashboard](img/kubecost_v13_5.png) diff --git a/doc/user/group/saml_sso/group_sync.md b/doc/user/group/saml_sso/group_sync.md index 2cea1bbbcd8..27482893bd6 100644 --- a/doc/user/group/saml_sso/group_sync.md +++ b/doc/user/group/saml_sso/group_sync.md @@ -109,9 +109,9 @@ Users granted: ### Automatic member removal -After a group sync, for GitLab subgroups, users who are not members of a mapped SAML -group are removed from the group. Users in the top-level group are assigned the -[default membership role](index.md#role). +After a group sync, users who are not members of a mapped SAML group are removed from the group. +On GitLab.com, users in the top-level group are assigned the +[default membership role](index.md#role) instead of being removed. For example, in the following diagram: diff --git a/doc/user/packages/container_registry/authenticate_with_container_registry.md b/doc/user/packages/container_registry/authenticate_with_container_registry.md index cdc7cbe947b..f48ba7bbf52 100644 --- a/doc/user/packages/container_registry/authenticate_with_container_registry.md +++ b/doc/user/packages/container_registry/authenticate_with_container_registry.md @@ -6,6 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Authenticate with the Container Registry **(FREE)** +<!--- start_remove The following content will be removed on remove_date: '2023-11-22' --> +WARNING: +[External authorization](../../admin_area/settings/external_authorization.md) will be enabled by default in GitLab 16.0. External authorization prevents personal access tokens and deploy tokens from accessing container and package registries and affects all users who use these tokens to access the registries. You can disable external authorization if you want to use personal access tokens and deploy tokens with the container or package registries. +<!--- end_remove --> + To authenticate with the Container Registry, you can use a: - [Personal access token](../../profile/personal_access_tokens.md). diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md index 096a8273440..104b9e0a666 100644 --- a/doc/user/packages/package_registry/index.md +++ b/doc/user/packages/package_registry/index.md @@ -43,6 +43,11 @@ For information on how to create and upload a package, view the GitLab documenta ## Authenticate with the registry +<!--- start_remove The following content will be removed on remove_date: '2023-11-22' --> +WARNING: +[External authorization](../../admin_area/settings/external_authorization.md) will be enabled by default in GitLab 16.0. External authorization prevents personal access tokens and deploy tokens from accessing container and package registries and affects all users who use these tokens to access the registries. You can disable external authorization if you want to use personal access tokens and deploy tokens with the container or package registries. +<!--- end_remove --> + Authentication depends on the package manager being used. For more information, see the docs on the specific package format you want to use. @@ -59,7 +64,6 @@ For most package types, the following credential types are valid: - [Job token](../../../ci/jobs/ci_job_token.md): allows access to packages in the project running the job for the users running the pipeline. Access to other external projects can be configured. - - If your organization uses two factor authentication (2FA), you must use a personal access token with the scope set to `api`. - If you are publishing a package via CI/CD pipelines, you must use a CI job token. diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md index 58750cdf5bc..470c4ab9c2f 100644 --- a/doc/user/project/merge_requests/getting_started.md +++ b/doc/user/project/merge_requests/getting_started.md @@ -96,6 +96,14 @@ When selected, GitLab creates a [to-do list item](../../todos.md) for each revie To learn more, read [Review a merge request](reviews/index.md). +#### Multiple reviewers for merge requests **(PREMIUM)** + +> Introduced in GitLab 13.7. + +Merge requests may often require multiple team members to review parts of the +proposed changes. You can add multiple reviewers to a merge request, making it +easier to see who is reviewing changes and who has approved changes. + ### Merge requests to close issues To create a merge request to close an issue when it's merged, you can either: diff --git a/doc/user/project/merge_requests/reviews/data_usage.md b/doc/user/project/merge_requests/reviews/data_usage.md index f17015aef4e..dd07f0b4a6e 100644 --- a/doc/user/project/merge_requests/reviews/data_usage.md +++ b/doc/user/project/merge_requests/reviews/data_usage.md @@ -15,21 +15,21 @@ Suggested Reviewers is the first user-facing GitLab machine learning (ML) powere When a Project Maintainer or Owner enables Suggested Reviewers in project settings GitLab kicks off a data extraction job for the project which leverages the Merge Request API to understand pattern of review including recency, domain experience, and frequency to suggest an appropriate reviewer. -This data extraction job can take a few hours to complete (possibly up to a day), which is largely dependent on the size of the project. The process is automated and no action is needed during this process. Once data extraction is complete, you will start getting suggestions in merge requests. +This data extraction job can take a few hours to complete (possibly up to a day), which is largely dependent on the size of the project. The process is automated and no action is needed during this process. Once data extraction is complete, you start getting suggestions in merge requests. ### Generating suggestions -Once Suggested Reviewers is enabled and the data extraction is complete, new merge requests or new commits to existing merge requests will automatically trigger a Suggested Reviewers ML model inference and generate up to 5 suggested reviewers. These suggestions are contextual to the changes in the merge request. Additional commits to merge requests may change the reviewer suggestions which will automatically update in the reviewer dropdown list. +Once Suggested Reviewers is enabled and the data extraction is complete, new merge requests or new commits to existing merge requests automatically trigger a Suggested Reviewers ML model inference and generate up to 5 suggested reviewers. These suggestions are contextual to the changes in the merge request. Additional commits to merge requests may change the reviewer suggestions, which are automatically updated in the reviewer dropdown list. ## Progressive enhancement -This feature is designed as a progressive enhancement to the existing GitLab Reviewers functionality. The GitLab Reviewer UI will only offer suggestions if the ML engine is able to provide a recommendation. In the event of an issue or model inference failure, the feature will gracefully degrade. At no point with the usage of Suggested Reviewers prevent a user from being able to manually set a reviewer. +This feature is designed as a progressive enhancement to the existing GitLab Reviewers functionality. The GitLab Reviewer UI only offers suggestions if the ML engine is able to provide a recommendation. In the event of an issue or model inference failure, the feature gracefully degrades. At no point with the usage of Suggested Reviewers prevent a user from being able to manually set a reviewer. ## Model Accuracy -Organizations use many different processes for code review. Some focus on senior engineers reviewing junior engineer's code, others have hierarchical organizational structure based reviews. Suggested Reviewers is focused on contextual reviewers based on historical merge request activity by users. While we will continue evolving the underlying ML model to better serve various code review use cases and processes Suggested Reviewers does not replace the usage of other code review features like Code Owners and [Approval Rules](../approvals/rules.md). Reviewer selection is highly subjective therefore, we do not expect Suggested Reviewers to provide perfect suggestions every time. +Organizations use many different processes for code review. Some focus on senior engineers reviewing junior engineer's code, others have hierarchical organizational structure based reviews. Suggested Reviewers is focused on contextual reviewers based on historical merge request activity by users. While we continue evolving the underlying ML model to better serve various code review use cases and processes Suggested Reviewers does not replace the usage of other code review features like Code Owners and [Approval Rules](../approvals/rules.md). Reviewer selection is highly subjective therefore, we do not expect Suggested Reviewers to provide perfect suggestions every time. -Through analysis of beta customer usage, we find that the Suggested Reviewers ML model provides suggestions that are adopted in 60% of cases. We will be introducing a feedback mechanism into the Suggested Reviewers feature in the future to allow users to flag bad reviewer suggestions to help improve the model. Additionally we will be offering an opt-in feature in the future which will allow the model to use your project's data for training the underlying model. +Through analysis of beta customer usage, we find that the Suggested Reviewers ML model provides suggestions that are adopted in 60% of cases. We plan to introduce a feedback mechanism into the Suggested Reviewers feature in the future to allow users to flag bad reviewer suggestions to help improve the model. Additionally we plan to offer an opt-in feature in the future which allows the model to use your project's data for training the underlying model. ## Off by default diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md index ead1f43e4a3..5d89576e587 100644 --- a/doc/user/project/web_ide/index.md +++ b/doc/user/project/web_ide/index.md @@ -238,7 +238,13 @@ There are two ways to preview Markdown content in the Web IDE: 1. Right-click or use the keyboard shortcut `Command/Control + Shift + P` and select **Preview Markdown** to toggle a live Markdown preview panel. -## Live Preview +<!--- start_remove The following content will be removed on remove_date: '2023-02-01' --> + +## Live Preview (removed) + +WARNING: +This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108627) in GitLab 15.8 +and is planned for removal in 15.9. This change is a breaking change. > [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/213853) from _Client Side Evaluation_ to _Live Preview_ in GitLab 13.0. @@ -283,6 +289,8 @@ An example `package.json`: } ``` +<!--- end_remove --> + ## Interactive Web Terminals for the Web IDE > [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/211685) from GitLab Ultimate to GitLab Free in 13.1. diff --git a/doc/user/project/web_ide_beta/index.md b/doc/user/project/web_ide_beta/index.md index 4f84110a038..ad9afef7139 100644 --- a/doc/user/project/web_ide_beta/index.md +++ b/doc/user/project/web_ide_beta/index.md @@ -96,7 +96,7 @@ If you do not want to use the Web IDE Beta, you can change your personal prefere ## Known issues The [Web Terminal](../web_ide/index.md#interactive-web-terminals-for-the-web-ide) -and [Live Preview](../web_ide/index.md#live-preview) are not available in the Web IDE Beta. +and [Live Preview](../web_ide/index.md#live-preview-removed) are not available in the Web IDE Beta. These features might become available at a later date. diff --git a/lib/api/api.rb b/lib/api/api.rb index 5e449022676..81b96207863 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -164,7 +164,7 @@ module API namespace do after do - ::Users::ActivityService.new(@current_user).execute + ::Users::ActivityService.new(author: @current_user, project: @project, namespace: @group).execute end # Mount endpoints to include in the OpenAPI V2 documentation here diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb index 56db6ee4c5c..816b8deb461 100644 --- a/lib/api/helpers/internal_helpers.rb +++ b/lib/api/helpers/internal_helpers.rb @@ -58,7 +58,9 @@ module API def log_user_activity(actor) commands = Gitlab::GitAccess::DOWNLOAD_COMMANDS - ::Users::ActivityService.new(actor).execute if commands.include?(params[:action]) + return unless commands.include?(params[:action]) + + ::Users::ActivityService.new(author: actor, namespace: project&.namespace, project: project).execute end def redis_ping diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index c105288fff0..a163cf37d10 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -250,8 +250,8 @@ module Gitlab prometheus_enabled: alt_usage_data(fallback: nil) { Gitlab::Prometheus::Internal.prometheus_enabled? }, prometheus_metrics_enabled: alt_usage_data(fallback: nil) { Gitlab::Metrics.prometheus_metrics_enabled? }, reply_by_email_enabled: alt_usage_data(fallback: nil) { Gitlab::IncomingEmail.enabled? }, + web_ide_clientside_preview_enabled: alt_usage_data(fallback: nil) { false }, signup_enabled: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.allow_signup? }, - web_ide_clientside_preview_enabled: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? }, grafana_link_enabled: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.grafana_enabled? }, gitpod_enabled: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.gitpod_enabled? } } diff --git a/lib/gitlab/usage_data_counters/editor_unique_counter.rb b/lib/gitlab/usage_data_counters/editor_unique_counter.rb index 0b448f68153..8ec94cb9aa6 100644 --- a/lib/gitlab/usage_data_counters/editor_unique_counter.rb +++ b/lib/gitlab/usage_data_counters/editor_unique_counter.rb @@ -7,7 +7,6 @@ module Gitlab EDIT_BY_SFE = 'g_edit_by_sfe' EDIT_BY_WEB_IDE = 'g_edit_by_web_ide' EDIT_CATEGORY = 'ide_edit' - EDIT_BY_LIVE_PREVIEW = 'g_edit_by_live_preview' class << self def track_web_ide_edit_action(author:, time: Time.zone.now, project:) @@ -39,10 +38,6 @@ module Gitlab count_unique(events, date_from, date_to) end - def track_live_preview_edit_action(author:, time: Time.zone.now, project:) - track_unique_action(EDIT_BY_LIVE_PREVIEW, author, time, project) - end - private def track_unique_action(event_name, author, time, project = nil) diff --git a/lib/gitlab/usage_data_counters/web_ide_counter.rb b/lib/gitlab/usage_data_counters/web_ide_counter.rb index f2753c8f215..904729f114f 100644 --- a/lib/gitlab/usage_data_counters/web_ide_counter.rb +++ b/lib/gitlab/usage_data_counters/web_ide_counter.rb @@ -27,18 +27,6 @@ module Gitlab count('pipelines') end - def increment_previews_count - return unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? - - count('previews') - end - - def increment_previews_success_count - return unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? - - count('previews_success') - end - private def redis_key(event) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f55eddb3eaf..e2727684b12 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -5152,6 +5152,9 @@ msgstr "" msgid "Approved" msgstr "" +msgid "Approved MRs" +msgstr "" + msgid "Approved the current merge request." msgstr "" @@ -5445,6 +5448,9 @@ msgstr "" msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user." msgstr "" +msgid "Ascending" +msgstr "" + msgid "Ask again later" msgstr "" @@ -8765,6 +8771,9 @@ msgstr "" msgid "CiVariable|Create wildcard" msgstr "" +msgid "CiVariable|Define a CI/CD variable in the UI" +msgstr "" + msgid "CiVariable|New environment" msgstr "" @@ -8959,6 +8968,9 @@ msgstr "" msgid "Closed %{epicTimeagoDate}" msgstr "" +msgid "Closed MRs" +msgstr "" + msgid "Closed date" msgstr "" @@ -11060,27 +11072,12 @@ msgstr "" msgid "ContributionAnalytics|%{created} created, %{merged} merged, %{closed} closed." msgstr "" -msgid "ContributionAnalytics|%{pushes} by %{contributors}." -msgstr "" - -msgid "ContributionAnalytics|Approved MRs" -msgstr "" - -msgid "ContributionAnalytics|Closed MRs" -msgstr "" - -msgid "ContributionAnalytics|Closed issues" +msgid "ContributionAnalytics|%{pushes}, more than %{commits} by %{contributors}." msgstr "" msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}" msgstr "" -msgid "ContributionAnalytics|Contributions per group member" -msgstr "" - -msgid "ContributionAnalytics|Failed to load the contribution stats" -msgstr "" - msgid "ContributionAnalytics|Issues" msgstr "" @@ -11093,18 +11090,9 @@ msgstr "" msgid "ContributionAnalytics|Last week" msgstr "" -msgid "ContributionAnalytics|Loading contribution stats for group members" -msgstr "" - msgid "ContributionAnalytics|Merge requests" msgstr "" -msgid "ContributionAnalytics|Merged MRs" -msgstr "" - -msgid "ContributionAnalytics|Name" -msgstr "" - msgid "ContributionAnalytics|No issues for the selected time period." msgstr "" @@ -11114,15 +11102,6 @@ msgstr "" msgid "ContributionAnalytics|No pushes for the selected time period." msgstr "" -msgid "ContributionAnalytics|Opened MRs" -msgstr "" - -msgid "ContributionAnalytics|Opened issues" -msgstr "" - -msgid "ContributionAnalytics|Pushed" -msgstr "" - msgid "ContributionAnalytics|The given date range is larger than 31 days" msgstr "" @@ -11132,10 +11111,10 @@ msgstr "" msgid "ContributionAnalytics|There is too much data to calculate. Try lowering the period_limit setting in the insights configuration file." msgstr "" -msgid "ContributionAnalytics|Total Contributions" +msgid "Contributions for %{calendar_date}" msgstr "" -msgid "Contributions for %{calendar_date}" +msgid "Contributions per group member" msgstr "" msgid "Contributor" @@ -14110,6 +14089,9 @@ msgstr "" msgid "Deprioritize label" msgstr "" +msgid "Descending" +msgstr "" + msgid "Describe the goal of the changes and what reviewers should be aware of." msgstr "" @@ -20816,9 +20798,6 @@ msgstr "" msgid "IDE" msgstr "" -msgid "IDE|Back" -msgstr "" - msgid "IDE|Commit" msgstr "" @@ -20828,21 +20807,9 @@ msgstr "" msgid "IDE|Edit" msgstr "" -msgid "IDE|Get started with Live Preview" -msgstr "" - msgid "IDE|Go to project" msgstr "" -msgid "IDE|Live Preview" -msgstr "" - -msgid "IDE|Preview your web application using Web IDE client-side evaluation." -msgstr "" - -msgid "IDE|Refresh preview" -msgstr "" - msgid "IDE|Review" msgstr "" @@ -23958,10 +23925,10 @@ msgstr "" msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}" msgstr "" -msgid "JiraService|Sign in to GitLab to link namespaces." +msgid "JiraService|Sign in to GitLab to get started." msgstr "" -msgid "JiraService|Sign in to GitLab.com to get started." +msgid "JiraService|Sign in to GitLab to link namespaces." msgstr "" msgid "JiraService|This feature requires a Premium plan." @@ -25255,9 +25222,6 @@ msgstr "" msgid "List your Bitbucket Server repositories" msgstr "" -msgid "Live preview" -msgstr "" - msgid "Load more" msgstr "" @@ -25270,6 +25234,9 @@ msgstr "" msgid "Loading %{name}" msgstr "" +msgid "Loading contribution stats for group members" +msgstr "" + msgid "Loading files, directories, and submodules in the path %{path} for commit reference %{ref}" msgstr "" @@ -25501,9 +25468,6 @@ msgstr "" msgid "Manage %{workspace} labels" msgstr "" -msgid "Manage Web IDE features." -msgstr "" - msgid "Manage access" msgstr "" @@ -26525,6 +26489,9 @@ msgstr "" msgid "Merged" msgstr "" +msgid "Merged MRs" +msgstr "" + msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes." msgstr "" @@ -29427,6 +29394,12 @@ msgstr "" msgid "Opened" msgstr "" +msgid "Opened MRs" +msgstr "" + +msgid "Opened issues" +msgstr "" + msgid "OpenedNDaysAgo|Created" msgstr "" @@ -31937,9 +31910,6 @@ msgstr "" msgid "Preview" msgstr "" -msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} " -msgstr "" - msgid "Preview Markdown" msgstr "" @@ -34634,6 +34604,9 @@ msgstr "" msgid "PushRule|Reject unverified users" msgstr "" +msgid "Pushed" +msgstr "" + msgid "Pushes" msgstr "" @@ -39957,6 +39930,9 @@ msgstr "" msgid "Something went wrong while fetching details" msgstr "" +msgid "Something went wrong while fetching group member contributions" +msgstr "" + msgid "Something went wrong while fetching latest comments." msgstr "" @@ -44494,6 +44470,9 @@ msgstr "" msgid "Total" msgstr "" +msgid "Total Contributions" +msgstr "" + msgid "Total Score" msgstr "" diff --git a/package.json b/package.json index 0c029a83e6d..246a022496f 100644 --- a/package.json +++ b/package.json @@ -51,14 +51,13 @@ "@apollo/client": "^3.5.10", "@babel/core": "^7.18.5", "@babel/preset-env": "^7.18.2", - "@codesandbox/sandpack-client": "^1.2.2", "@cubejs-client/core": "^0.31.15", "@cubejs-client/vue": "^0.31.19", "@gitlab/at.js": "1.5.7", "@gitlab/favicon-overlay": "2.0.0", "@gitlab/fonts": "^1.2.0", "@gitlab/svgs": "3.18.0", - "@gitlab/ui": "54.1.1", + "@gitlab/ui": "54.1.2", "@gitlab/visual-review-tools": "1.7.3", "@gitlab/web-ide": "0.0.1-dev-20230120231236", "@rails/actioncable": "6.1.4-7", @@ -109,7 +108,6 @@ "cache-loader": "^4.1.0", "canvas-confetti": "^1.4.0", "clipboard": "^2.0.8", - "codesandbox-api": "0.0.23", "compression-webpack-plugin": "^5.0.2", "copy-webpack-plugin": "^6.4.1", "core-js": "^3.27.2", @@ -228,10 +226,10 @@ "cheerio": "^1.0.0-rc.9", "commander": "^2.20.3", "custom-jquery-matchers": "^2.1.0", - "eslint": "8.29.0", + "eslint": "8.32.0", "eslint-import-resolver-jest": "3.0.2", "eslint-import-resolver-webpack": "0.13.2", - "eslint-plugin-import": "^2.26.0", + "eslint-plugin-import": "^2.27.5", "eslint-plugin-no-jquery": "2.7.0", "eslint-plugin-no-unsanitized": "^4.0.2", "gettext-extractor": "^3.5.3", diff --git a/spec/controllers/projects/service_ping_controller_spec.rb b/spec/controllers/projects/service_ping_controller_spec.rb index 10d4b897564..601dfd9b011 100644 --- a/spec/controllers/projects/service_ping_controller_spec.rb +++ b/spec/controllers/projects/service_ping_controller_spec.rb @@ -42,83 +42,6 @@ RSpec.describe Projects::ServicePingController do end end - describe 'POST #web_ide_clientside_preview' do - subject { post :web_ide_clientside_preview, params: { namespace_id: project.namespace, project_id: project } } - - context 'when web ide clientside preview is enabled' do - before do - stub_application_setting(web_ide_clientside_preview_enabled: true) - end - - it_behaves_like 'counter is not increased' - it_behaves_like 'counter is increased', 'WEB_IDE_PREVIEWS_COUNT' - end - - context 'when web ide clientside preview is not enabled' do - let(:user) { project.first_owner } - - before do - stub_application_setting(web_ide_clientside_preview_enabled: false) - end - - it 'returns 404' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - describe 'POST #web_ide_clientside_preview_success' do - subject { post :web_ide_clientside_preview_success, params: { namespace_id: project.namespace, project_id: project } } - - context 'when web ide clientside preview is enabled' do - before do - stub_application_setting(web_ide_clientside_preview_enabled: true) - end - - it_behaves_like 'counter is not increased' - it_behaves_like 'counter is increased', 'WEB_IDE_PREVIEWS_SUCCESS_COUNT' - - context 'when the user has access to the project', :snowplow do - let(:user) { project.owner } - - it 'increases the live preview view counter' do - expect(Gitlab::UsageDataCounters::EditorUniqueCounter).to receive(:track_live_preview_edit_action).with(author: user, project: project) - - subject - - expect(response).to have_gitlab_http_status(:ok) - end - - it_behaves_like 'Snowplow event tracking with RedisHLL context' do - let(:project) { create(:project) } - let(:namespace) { project.namespace } - let(:category) { 'Gitlab::UsageDataCounters::EditorUniqueCounter' } - let(:action) { 'ide_edit' } - let(:property) { 'g_edit_by_live_preview' } - let(:label) { 'usage_activity_by_stage_monthly.create.action_monthly_active_users_ide_edit' } - let(:context) { [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event_name).to_context] } - let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } - end - end - end - - context 'when web ide clientside preview is not enabled' do - let(:user) { project.owner } - - before do - stub_application_setting(web_ide_clientside_preview_enabled: false) - end - - it 'returns 404' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - describe 'POST #web_ide_pipelines_count' do subject { post :web_ide_pipelines_count, params: { namespace_id: project.namespace, project_id: project } } diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 78b3cc63b08..1f7d169bae5 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -221,7 +221,7 @@ RSpec.describe SessionsController do expect(Gitlab::Metrics).to receive(:counter) .with(:successful_login_captcha_total, anything) .and_return(counter) - expect(Gitlab::Metrics).to receive(:counter).and_call_original + expect(Gitlab::Metrics).to receive(:counter).at_least(1).time.and_call_original post(:create, params: { user: user_params }, session: sesion_params) end diff --git a/spec/features/ide/clientside_preview_csp_spec.rb b/spec/features/ide/clientside_preview_csp_spec.rb deleted file mode 100644 index 04427a5c294..00000000000 --- a/spec/features/ide/clientside_preview_csp_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'IDE Clientside Preview CSP', feature_category: :web_ide do - let_it_be(:user) { create(:user) } - - shared_context 'disable feature' do - before do - stub_application_setting(web_ide_clientside_preview_enabled: false) - end - end - - it_behaves_like 'setting CSP', 'frame-src' do - let(:allowlisted_url) { 'https://sandbox.gitlab-static.test' } - let(:extended_controller_class) { IdeController } - - subject do - visit ide_path - - response_headers['Content-Security-Policy'] - end - - before do - stub_application_setting(web_ide_clientside_preview_enabled: true) - stub_application_setting(web_ide_clientside_preview_bundler_url: allowlisted_url) - - sign_in(user) - end - end -end diff --git a/spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js index 7838e4884d8..71826628ffd 100644 --- a/spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js +++ b/spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js @@ -33,7 +33,6 @@ describe('Ci variable modal', () => { isProtectedByDefault: false, maskedEnvironmentVariablesLink: '/variables-link', maskableRegex, - protectedEnvironmentVariablesLink: '/protected-link', }; const defaultProps = { diff --git a/spec/frontend/ide/components/panes/right_spec.js b/spec/frontend/ide/components/panes/right_spec.js index 294f5eee863..1d81c3ea89d 100644 --- a/spec/frontend/ide/components/panes/right_spec.js +++ b/spec/frontend/ide/components/panes/right_spec.js @@ -68,31 +68,6 @@ describe('ide/components/panes/right.vue', () => { }); }); - describe('clientside live preview tab', () => { - it('is shown if there is a packageJson and clientsidePreviewEnabled', () => { - Vue.set(store.state.entries, 'package.json', { - name: 'package.json', - }); - store.state.clientsidePreviewEnabled = true; - - createComponent(); - - expect(wrapper.findComponent(CollapsibleSidebar).props('extensionTabs')).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - show: true, - title: 'Live preview', - views: expect.arrayContaining([ - expect.objectContaining({ - name: rightSidebarViews.clientSidePreview.name, - }), - ]), - }), - ]), - ); - }); - }); - describe('terminal tab', () => { beforeEach(() => { createComponent(); diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js deleted file mode 100644 index 51e6a9d9034..00000000000 --- a/spec/frontend/ide/components/preview/clientside_spec.js +++ /dev/null @@ -1,416 +0,0 @@ -import { GlLoadingIcon } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import Vue, { nextTick } from 'vue'; -import { dispatch } from 'codesandbox-api'; -import { SandpackClient } from '@codesandbox/sandpack-client'; -import Vuex from 'vuex'; -import waitForPromises from 'helpers/wait_for_promises'; -import Clientside from '~/ide/components/preview/clientside.vue'; -import { PING_USAGE_PREVIEW_KEY, PING_USAGE_PREVIEW_SUCCESS_KEY } from '~/ide/constants'; -import eventHub from '~/ide/eventhub'; - -jest.mock('@codesandbox/sandpack-client', () => ({ - SandpackClient: jest.fn(), -})); - -Vue.use(Vuex); - -const dummyPackageJson = () => ({ - raw: JSON.stringify({ - main: 'index.js', - }), -}); -const expectedSandpackOptions = () => ({ - files: {}, - entry: '/index.js', - showOpenInCodeSandbox: true, -}); -const expectedSandpackSettings = () => ({ - fileResolver: { - isFile: expect.any(Function), - readFile: expect.any(Function), - }, -}); - -describe('IDE clientside preview', () => { - let wrapper; - let store; - const storeActions = { - getFileData: jest.fn().mockReturnValue(Promise.resolve({})), - getRawFileData: jest.fn().mockReturnValue(Promise.resolve('')), - }; - const storeClientsideActions = { - pingUsage: jest.fn().mockReturnValue(Promise.resolve({})), - }; - const dispatchCodesandboxReady = () => dispatch({ type: 'done' }); - - const createComponent = ({ state, getters } = {}) => { - store = new Vuex.Store({ - state: { - entries: {}, - links: {}, - ...state, - }, - getters: { - packageJson: () => '', - currentProject: () => ({ - visibility: 'public', - }), - ...getters, - }, - actions: storeActions, - modules: { - clientside: { - namespaced: true, - actions: storeClientsideActions, - }, - }, - }); - - wrapper = shallowMount(Clientside, { - store, - }); - }; - - const createInitializedComponent = () => { - createComponent(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ - sandpackReady: true, - client: { - cleanup: jest.fn(), - updatePreview: jest.fn(), - }, - }); - }; - - afterEach(() => { - wrapper.destroy(); - }); - - describe('without main entry', () => { - it('creates sandpack client', () => { - createComponent(); - expect(SandpackClient).not.toHaveBeenCalled(); - }); - }); - describe('with main entry', () => { - beforeEach(() => { - createComponent({ getters: { packageJson: dummyPackageJson } }); - - return waitForPromises(); - }); - - it('creates sandpack client', () => { - expect(SandpackClient).toHaveBeenCalledWith( - '#ide-preview', - expectedSandpackOptions(), - expectedSandpackSettings(), - ); - }); - - it('pings usage', () => { - expect(storeClientsideActions.pingUsage).toHaveBeenCalledTimes(1); - expect(storeClientsideActions.pingUsage).toHaveBeenCalledWith( - expect.anything(), - PING_USAGE_PREVIEW_KEY, - ); - }); - - it('pings usage success', async () => { - dispatchCodesandboxReady(); - await nextTick(); - expect(storeClientsideActions.pingUsage).toHaveBeenCalledTimes(2); - expect(storeClientsideActions.pingUsage).toHaveBeenCalledWith( - expect.anything(), - PING_USAGE_PREVIEW_SUCCESS_KEY, - ); - }); - }); - - describe('with codesandboxBundlerUrl', () => { - const TEST_BUNDLER_URL = 'https://test.gitlab-static.test'; - - beforeEach(() => { - createComponent({ - getters: { packageJson: dummyPackageJson }, - state: { codesandboxBundlerUrl: TEST_BUNDLER_URL }, - }); - - return waitForPromises(); - }); - - it('creates sandpack client with bundlerURL', () => { - expect(SandpackClient).toHaveBeenCalledWith('#ide-preview', expectedSandpackOptions(), { - ...expectedSandpackSettings(), - bundlerURL: TEST_BUNDLER_URL, - }); - }); - }); - - describe('with codesandboxBundlerURL', () => { - beforeEach(() => { - createComponent({ getters: { packageJson: dummyPackageJson } }); - - return waitForPromises(); - }); - - it('creates sandpack client', () => { - expect(SandpackClient).toHaveBeenCalledWith( - '#ide-preview', - { - files: {}, - entry: '/index.js', - showOpenInCodeSandbox: true, - }, - { - fileResolver: { - isFile: expect.any(Function), - readFile: expect.any(Function), - }, - }, - ); - }); - }); - - describe('computed', () => { - describe('normalizedEntries', () => { - it('returns flattened list of blobs with content', () => { - createComponent({ - state: { - entries: { - 'index.js': { type: 'blob', raw: 'test' }, - 'index2.js': { type: 'blob', content: 'content' }, - tree: { type: 'tree' }, - empty: { type: 'blob' }, - }, - }, - }); - - expect(wrapper.vm.normalizedEntries).toEqual({ - '/index.js': { - code: 'test', - }, - '/index2.js': { - code: 'content', - }, - }); - }); - }); - - describe('mainEntry', () => { - it('returns false when package.json is empty', () => { - createComponent(); - expect(wrapper.vm.mainEntry).toBe(false); - }); - - it('returns main key from package.json', () => { - createComponent({ getters: { packageJson: dummyPackageJson } }); - expect(wrapper.vm.mainEntry).toBe('index.js'); - }); - }); - - describe('showPreview', () => { - it('returns false if no mainEntry', () => { - createComponent(); - expect(wrapper.vm.showPreview).toBe(false); - }); - - it('returns false if loading and mainEntry exists', () => { - createComponent({ getters: { packageJson: dummyPackageJson } }); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ loading: true }); - - expect(wrapper.vm.showPreview).toBe(false); - }); - - it('returns true if not loading and mainEntry exists', () => { - createComponent({ getters: { packageJson: dummyPackageJson } }); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ loading: false }); - - expect(wrapper.vm.showPreview).toBe(true); - }); - }); - - describe('showEmptyState', () => { - it('returns true if no mainEntry exists', () => { - createComponent(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ loading: false }); - expect(wrapper.vm.showEmptyState).toBe(true); - }); - - it('returns false if loading', () => { - createComponent(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ loading: true }); - - expect(wrapper.vm.showEmptyState).toBe(false); - }); - - it('returns false if not loading and mainEntry exists', () => { - createComponent({ getters: { packageJson: dummyPackageJson } }); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ loading: false }); - - expect(wrapper.vm.showEmptyState).toBe(false); - }); - }); - - describe('showOpenInCodeSandbox', () => { - it('returns true when visibility is public', () => { - createComponent({ getters: { currentProject: () => ({ visibility: 'public' }) } }); - - expect(wrapper.vm.showOpenInCodeSandbox).toBe(true); - }); - - it('returns false when visibility is private', () => { - createComponent({ getters: { currentProject: () => ({ visibility: 'private' }) } }); - - expect(wrapper.vm.showOpenInCodeSandbox).toBe(false); - }); - }); - - describe('sandboxOpts', () => { - beforeEach(() => { - createComponent({ - state: { - entries: { - 'index.js': { type: 'blob', raw: 'test' }, - 'package.json': dummyPackageJson(), - }, - }, - getters: { - packageJson: dummyPackageJson, - }, - }); - }); - - it('returns sandbox options', () => { - expect(wrapper.vm.sandboxOpts).toEqual({ - files: { - '/index.js': { - code: 'test', - }, - '/package.json': { - code: '{"main":"index.js"}', - }, - }, - entry: '/index.js', - showOpenInCodeSandbox: true, - }); - }); - }); - }); - - describe('methods', () => { - describe('loadFileContent', () => { - beforeEach(() => { - createComponent(); - return wrapper.vm.loadFileContent('package.json'); - }); - - it('calls getFileData', () => { - expect(storeActions.getFileData).toHaveBeenCalledWith(expect.any(Object), { - path: 'package.json', - makeFileActive: false, - }); - }); - - it('calls getRawFileData', () => { - expect(storeActions.getRawFileData).toHaveBeenCalledWith(expect.any(Object), { - path: 'package.json', - }); - }); - }); - - describe('update', () => { - it('initializes client if client is empty', () => { - createComponent({ getters: { packageJson: dummyPackageJson } }); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ sandpackReady: true }); - wrapper.vm.update(); - - return waitForPromises().then(() => { - expect(SandpackClient).toHaveBeenCalled(); - }); - }); - - it('calls updatePreview', () => { - createInitializedComponent(); - - wrapper.vm.update(); - - expect(wrapper.vm.client.updatePreview).toHaveBeenCalledWith(wrapper.vm.sandboxOpts); - }); - }); - - describe('on ide.files.change event', () => { - beforeEach(() => { - createInitializedComponent(); - - eventHub.$emit('ide.files.change'); - }); - - it('calls updatePreview', () => { - expect(wrapper.vm.client.updatePreview).toHaveBeenCalledWith(wrapper.vm.sandboxOpts); - }); - }); - }); - - describe('template', () => { - it('renders ide-preview element when showPreview is true', async () => { - createComponent({ getters: { packageJson: dummyPackageJson } }); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ loading: false }); - - await nextTick(); - expect(wrapper.find('#ide-preview').exists()).toBe(true); - }); - - it('renders empty state', async () => { - createComponent(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ loading: false }); - - await nextTick(); - expect(wrapper.text()).toContain( - 'Preview your web application using Web IDE client-side evaluation.', - ); - }); - - it('renders loading icon', async () => { - createComponent(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ loading: true }); - - await nextTick(); - expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true); - }); - }); - - describe('when destroyed', () => { - let spy; - - beforeEach(() => { - createInitializedComponent(); - spy = wrapper.vm.client.updatePreview; - wrapper.destroy(); - }); - - it('does not call updatePreview', () => { - expect(spy).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/spec/frontend/ide/components/preview/navigator_spec.js b/spec/frontend/ide/components/preview/navigator_spec.js deleted file mode 100644 index 043dcade858..00000000000 --- a/spec/frontend/ide/components/preview/navigator_spec.js +++ /dev/null @@ -1,161 +0,0 @@ -import { GlLoadingIcon } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import { listen } from 'codesandbox-api'; -import { nextTick } from 'vue'; -import { TEST_HOST } from 'helpers/test_constants'; -import ClientsideNavigator from '~/ide/components/preview/navigator.vue'; - -jest.mock('codesandbox-api', () => ({ - listen: jest.fn().mockReturnValue(jest.fn()), -})); - -describe('IDE clientside preview navigator', () => { - let wrapper; - let client; - let listenHandler; - - const findBackButton = () => wrapper.findAll('button').at(0); - const findForwardButton = () => wrapper.findAll('button').at(1); - const findRefreshButton = () => wrapper.findAll('button').at(2); - - beforeEach(() => { - listen.mockClear(); - client = { bundlerURL: TEST_HOST, iframe: { src: '' } }; - - wrapper = shallowMount(ClientsideNavigator, { propsData: { client } }); - [[listenHandler]] = listen.mock.calls; - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('renders readonly URL bar', async () => { - listenHandler({ type: 'urlchange', url: client.bundlerURL }); - await nextTick(); - expect(wrapper.find('input[readonly]').element.value).toBe('/'); - }); - - it('renders loading icon by default', () => { - expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true); - }); - - it('removes loading icon when done event is fired', async () => { - listenHandler({ type: 'done' }); - await nextTick(); - expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false); - }); - - it('does not count visiting same url multiple times', async () => { - listenHandler({ type: 'done' }); - listenHandler({ type: 'done', url: `${TEST_HOST}/url1` }); - listenHandler({ type: 'done', url: `${TEST_HOST}/url1` }); - await nextTick(); - expect(findBackButton().attributes('disabled')).toBe('disabled'); - }); - - it('unsubscribes from listen on destroy', () => { - const unsubscribeFn = listen(); - - wrapper.destroy(); - expect(unsubscribeFn).toHaveBeenCalled(); - }); - - describe('back button', () => { - beforeEach(async () => { - listenHandler({ type: 'done' }); - listenHandler({ type: 'urlchange', url: TEST_HOST }); - await nextTick(); - }); - - it('is disabled by default', () => { - expect(findBackButton().attributes('disabled')).toBe('disabled'); - }); - - it('is enabled when there is previous entry', async () => { - listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - await nextTick(); - findBackButton().trigger('click'); - expect(findBackButton().attributes()).not.toHaveProperty('disabled'); - }); - - it('is disabled when there is no previous entry', async () => { - listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - - await nextTick(); - findBackButton().trigger('click'); - - await nextTick(); - expect(findBackButton().attributes('disabled')).toBe('disabled'); - }); - - it('updates client iframe src', async () => { - listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url2` }); - await nextTick(); - findBackButton().trigger('click'); - - expect(client.iframe.src).toBe(`${TEST_HOST}/url1`); - }); - }); - - describe('forward button', () => { - beforeEach(async () => { - listenHandler({ type: 'done' }); - listenHandler({ type: 'urlchange', url: TEST_HOST }); - await nextTick(); - }); - - it('is disabled by default', () => { - expect(findForwardButton().attributes('disabled')).toBe('disabled'); - }); - - it('is enabled when there is next entry', async () => { - listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - - await nextTick(); - findBackButton().trigger('click'); - - await nextTick(); - expect(findForwardButton().attributes()).not.toHaveProperty('disabled'); - }); - - it('is disabled when there is no next entry', async () => { - listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - - await nextTick(); - findBackButton().trigger('click'); - - await nextTick(); - findForwardButton().trigger('click'); - - await nextTick(); - expect(findForwardButton().attributes('disabled')).toBe('disabled'); - }); - - it('updates client iframe src', async () => { - listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url2` }); - await nextTick(); - findBackButton().trigger('click'); - - expect(client.iframe.src).toBe(`${TEST_HOST}/url1`); - }); - }); - - describe('refresh button', () => { - const url = `${TEST_HOST}/some_url`; - beforeEach(async () => { - listenHandler({ type: 'done' }); - listenHandler({ type: 'urlchange', url }); - await nextTick(); - }); - - it('calls refresh with current path', () => { - client.iframe.src = 'something-other'; - findRefreshButton().trigger('click'); - - expect(client.iframe.src).toBe(url); - }); - }); -}); diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js index 24661e21cd0..d4166a3bd6d 100644 --- a/spec/frontend/ide/stores/getters_spec.js +++ b/spec/frontend/ide/stores/getters_spec.js @@ -294,18 +294,6 @@ describe('IDE store getters', () => { }); }); - describe('packageJson', () => { - it('returns package.json entry', () => { - localState.entries['package.json'] = { - name: 'package.json', - }; - - expect(getters.packageJson(localState)).toEqual({ - name: 'package.json', - }); - }); - }); - describe('canPushToBranch', () => { it.each` currentBranch | canPushCode | expectedValue diff --git a/spec/frontend/ide/stores/modules/clientside/actions_spec.js b/spec/frontend/ide/stores/modules/clientside/actions_spec.js deleted file mode 100644 index c2b9de192d9..00000000000 --- a/spec/frontend/ide/stores/modules/clientside/actions_spec.js +++ /dev/null @@ -1,38 +0,0 @@ -import MockAdapter from 'axios-mock-adapter'; -import { TEST_HOST } from 'helpers/test_constants'; -import testAction from 'helpers/vuex_action_helper'; -import { PING_USAGE_PREVIEW_KEY } from '~/ide/constants'; -import * as actions from '~/ide/stores/modules/clientside/actions'; -import axios from '~/lib/utils/axios_utils'; - -const TEST_PROJECT_URL = `${TEST_HOST}/lorem/ipsum`; -const TEST_USAGE_URL = `${TEST_PROJECT_URL}/service_ping/${PING_USAGE_PREVIEW_KEY}`; - -describe('IDE store module clientside actions', () => { - let rootGetters; - let mock; - - beforeEach(() => { - rootGetters = { - currentProject: { - web_url: TEST_PROJECT_URL, - }, - }; - mock = new MockAdapter(axios); - }); - - afterEach(() => { - mock.restore(); - }); - - describe('pingUsage', () => { - it('posts to usage endpoint', async () => { - const usageSpy = jest.fn(() => [200]); - - mock.onPost(TEST_USAGE_URL).reply(() => usageSpy()); - - await testAction(actions.pingUsage, PING_USAGE_PREVIEW_KEY, rootGetters, [], []); - expect(usageSpy).toHaveBeenCalled(); - }); - }); -}); diff --git a/spec/frontend/lib/utils/datetime/date_format_utility_spec.js b/spec/frontend/lib/utils/datetime/date_format_utility_spec.js index 2c3fa612740..a83b0ed9fbe 100644 --- a/spec/frontend/lib/utils/datetime/date_format_utility_spec.js +++ b/spec/frontend/lib/utils/datetime/date_format_utility_spec.js @@ -82,10 +82,6 @@ describe('date_format_utility.js', () => { ); }); - it('defaults to 00:00 if no time is provided', () => { - expect(utils.dateAndTimeToISOString(new Date('2021-08-21'))).toBe('2021-08-21T00:00:00.000Z'); - }); - it('throws if date in invalid', () => { expect(() => utils.dateAndTimeToISOString('Invalid date', '10:00')).toThrow( 'Argument should be a Date instance', diff --git a/spec/frontend/super_sidebar/components/create_menu_spec.js b/spec/frontend/super_sidebar/components/create_menu_spec.js index 77a3dbd67c9..b24c6b8de7f 100644 --- a/spec/frontend/super_sidebar/components/create_menu_spec.js +++ b/spec/frontend/super_sidebar/components/create_menu_spec.js @@ -1,4 +1,4 @@ -import { GlDisclosureDropdown } from '@gitlab/ui'; +import { GlDisclosureDropdown, GlTooltip } from '@gitlab/ui'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { __ } from '~/locale'; import CreateMenu from '~/super_sidebar/components/create_menu.vue'; @@ -8,6 +8,7 @@ describe('CreateMenu component', () => { let wrapper; const findGlDisclosureDropdown = () => wrapper.findComponent(GlDisclosureDropdown); + const findGlTooltip = () => wrapper.findComponent(GlTooltip); const createWrapper = () => { wrapper = shallowMountExtended(CreateMenu, { @@ -29,5 +30,10 @@ describe('CreateMenu component', () => { it('passes the groups to the disclosure dropdown', () => { expect(findGlDisclosureDropdown().props('items')).toBe(createNewMenuGroups); }); + + it("sets the toggle ID and tooltip's target", () => { + expect(findGlDisclosureDropdown().props('toggleId')).toBe(wrapper.vm.$options.toggleId); + expect(findGlTooltip().props('target')).toBe(`#${wrapper.vm.$options.toggleId}`); + }); }); }); diff --git a/spec/frontend_integration/ide/helpers/mock_data.js b/spec/frontend_integration/ide/helpers/mock_data.js index 8c9ec74541f..e012507a592 100644 --- a/spec/frontend_integration/ide/helpers/mock_data.js +++ b/spec/frontend_integration/ide/helpers/mock_data.js @@ -5,7 +5,5 @@ export const IDE_DATASET = { pipelinesEmptyStateSvgPath: '/test/pipelines_empty_state.svg', promotionSvgPath: '/test/promotion.svg', webIDEHelpPagePath: '/test/web_ide_help_page', - clientsidePreviewEnabled: 'true', renderWhitespaceInCode: 'false', - codesandboxBundlerUrl: 'test/codesandbox_bundler', }; diff --git a/spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb index bfbabd858f0..cb7970cacec 100644 --- a/spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb @@ -68,13 +68,10 @@ RSpec.describe Gitlab::UsageDataCounters::EditorUniqueCounter, :clean_gitlab_red it 'can return the count of actions per user deduplicated' do described_class.track_web_ide_edit_action(author: user1, project: project) - described_class.track_live_preview_edit_action(author: user1, project: project) described_class.track_snippet_editor_edit_action(author: user1, project: project) described_class.track_sfe_edit_action(author: user1, project: project) described_class.track_web_ide_edit_action(author: user2, time: time - 2.days, project: project) described_class.track_web_ide_edit_action(author: user3, time: time - 3.days, project: project) - described_class.track_live_preview_edit_action(author: user2, time: time - 2.days, project: project) - described_class.track_live_preview_edit_action(author: user3, time: time - 3.days, project: project) described_class.track_snippet_editor_edit_action(author: user3, time: time - 3.days, project: project) described_class.track_sfe_edit_action(author: user3, time: time - 3.days, project: project) diff --git a/spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb index b0e5bd18b66..d79fa66b983 100644 --- a/spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb @@ -34,46 +34,17 @@ RSpec.describe Gitlab::UsageDataCounters::WebIdeCounter, :clean_gitlab_redis_sha it_behaves_like 'counter examples', 'pipelines' end - describe 'previews counter' do - let(:setting_enabled) { true } - - before do - stub_application_setting(web_ide_clientside_preview_enabled: setting_enabled) - end - - context 'when web ide clientside preview is enabled' do - it_behaves_like 'counter examples', 'previews' - end - - context 'when web ide clientside preview is not enabled' do - let(:setting_enabled) { false } - - it 'does not increment the counter' do - redis_key = 'WEB_IDE_PREVIEWS_COUNT' - expect(described_class.total_count(redis_key)).to eq(0) - - 2.times { described_class.increment_previews_count } - - expect(described_class.total_count(redis_key)).to eq(0) - end - end - end - describe '.totals' do commits = 5 merge_requests = 3 views = 2 - previews = 4 terminals = 1 pipelines = 2 before do - stub_application_setting(web_ide_clientside_preview_enabled: true) - commits.times { described_class.increment_commits_count } merge_requests.times { described_class.increment_merge_requests_count } views.times { described_class.increment_views_count } - previews.times { described_class.increment_previews_count } terminals.times { described_class.increment_terminals_count } pipelines.times { described_class.increment_pipelines_count } end @@ -83,7 +54,6 @@ RSpec.describe Gitlab::UsageDataCounters::WebIdeCounter, :clean_gitlab_redis_sha web_ide_commits: commits, web_ide_views: views, web_ide_merge_requests: merge_requests, - web_ide_previews: previews, web_ide_terminals: terminals ) end diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 592ac280d32..0b2c0f9170e 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -739,7 +739,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures, feature_category: :servic expect(subject[:container_registry_enabled]).to eq(Gitlab.config.registry.enabled) expect(subject[:dependency_proxy_enabled]).to eq(Gitlab.config.dependency_proxy.enabled) expect(subject[:gitlab_shared_runners_enabled]).to eq(Gitlab.config.gitlab_ci.shared_runners_enabled) - expect(subject[:web_ide_clientside_preview_enabled]).to eq(Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?) expect(subject[:grafana_link_enabled]).to eq(Gitlab::CurrentSettings.grafana_enabled?) expect(subject[:gitpod_enabled]).to eq(Gitlab::CurrentSettings.gitpod_enabled?) end diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb index 1ad0f20b77e..35851fff6c8 100644 --- a/spec/requests/api/api_spec.rb +++ b/spec/requests/api/api_spec.rb @@ -12,8 +12,22 @@ RSpec.describe API::API, feature_category: :authentication_and_authorization do let(:user) { create(:user, last_activity_on: Date.yesterday) } it 'updates the users last_activity_on to the current date' do + expect(Users::ActivityService).to receive(:new).with(author: user, project: nil, namespace: nil).and_call_original + expect { get api('/groups', user) }.to change { user.reload.last_activity_on }.to(Date.today) end + + context "with a project-specific path" do + let_it_be(:project) { create(:project, :public) } + let_it_be(:user) { project.first_owner } + + it "passes correct arguments to ActivityService" do + activity_args = { author: user, project: project, namespace: project.group } + expect(Users::ActivityService).to receive(:new).with(activity_args).and_call_original + + get(api("/projects/#{project.id}/issues", user)) + end + end end describe 'User with only read_api scope personal access token' do diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb index 767f3e8b5b5..ca32271f573 100644 --- a/spec/requests/api/internal/base_spec.rb +++ b/spec/requests/api/internal/base_spec.rb @@ -651,6 +651,12 @@ RSpec.describe API::Internal::Base, feature_category: :authentication_and_author headers: gitlab_shell_internal_api_request_header ) end + + it "updates user's activity data" do + expect(::Users::ActivityService).to receive(:new).with(author: user, namespace: project.namespace, project: project) + + request + end end end end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 1b6a5182531..664fc7dde7a 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -843,10 +843,6 @@ RSpec.describe 'project routing' do end describe Projects::ServicePingController, 'routing' do - it 'routes to service_ping#web_ide_clientside_preview' do - expect(post('/gitlab/gitlabhq/service_ping/web_ide_clientside_preview')).to route_to('projects/service_ping#web_ide_clientside_preview', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - it 'routes to service_ping#web_ide_pipelines_count' do expect(post('/gitlab/gitlabhq/service_ping/web_ide_pipelines_count')).to route_to('projects/service_ping#web_ide_pipelines_count', namespace_id: 'gitlab', project_id: 'gitlabhq') end diff --git a/spec/services/users/activity_service_spec.rb b/spec/services/users/activity_service_spec.rb index 47a4b943d83..6c0d93f568a 100644 --- a/spec/services/users/activity_service_spec.rb +++ b/spec/services/users/activity_service_spec.rb @@ -7,9 +7,21 @@ RSpec.describe Users::ActivityService do let(:user) { create(:user, last_activity_on: last_activity_on) } - subject { described_class.new(user) } + subject { described_class.new(author: user) } describe '#execute', :clean_gitlab_redis_shared_state do + shared_examples 'does not update last_activity_on' do + it 'does not update user attribute' do + expect { subject.execute }.not_to change(user, :last_activity_on) + end + + it 'does not track Snowplow event' do + subject.execute + + expect_no_snowplow_event + end + end + context 'when last activity is nil' do let(:last_activity_on) { nil } @@ -41,13 +53,29 @@ RSpec.describe Users::ActivityService do subject.execute end + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + subject(:record_activity) { described_class.new(author: user, namespace: namespace, project: project).execute } + + let(:feature_flag_name) { :route_hll_to_snowplow_phase3 } + let(:category) { described_class.name } + let(:action) { 'perform_action' } + let(:label) { 'redis_hll_counters.manage.unique_active_users_monthly' } + let(:namespace) { build(:group) } + let(:project) { build(:project) } + let(:context) do + payload = Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, + event: 'unique_active_user').to_context + [Gitlab::Json.dump(payload)] + end + end end context 'when a bad object is passed' do let(:fake_object) { double(username: 'hello') } it 'does not record activity' do - service = described_class.new(fake_object) + service = described_class.new(author: fake_object) expect(service).not_to receive(:record_activity) @@ -58,9 +86,7 @@ RSpec.describe Users::ActivityService do context 'when last activity is today' do let(:last_activity_on) { Date.today } - it 'does not update last_activity_on' do - expect { subject.execute }.not_to change(user, :last_activity_on) - end + it_behaves_like 'does not update last_activity_on' it 'does not try to obtain ExclusiveLease' do expect(Gitlab::ExclusiveLease).not_to receive(:new).with("activity_service:#{user.id}", anything) @@ -76,19 +102,17 @@ RSpec.describe Users::ActivityService do allow(Gitlab::Database).to receive(:read_only?).and_return(true) end - it 'does not update last_activity_on' do - expect { subject.execute }.not_to change(user, :last_activity_on) - end + it_behaves_like 'does not update last_activity_on' end context 'when a lease could not be obtained' do let(:last_activity_on) { nil } - it 'does not update last_activity_on' do + before do stub_exclusive_lease_taken("activity_service:#{user.id}", timeout: 1.minute.to_i) - - expect { subject.execute }.not_to change(user, :last_activity_on) end + + it_behaves_like 'does not update last_activity_on' end end @@ -104,7 +128,7 @@ RSpec.describe Users::ActivityService do end let(:service) do - service = described_class.new(user) + service = described_class.new(author: user) ::Gitlab::Database::LoadBalancing::Session.clear_session @@ -123,7 +147,7 @@ RSpec.describe Users::ActivityService do end context 'database load balancing is not configured' do - let(:service) { described_class.new(user) } + let(:service) { described_class.new(author: user) } it 'updates user without error' do service.execute diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb index 438f0d129b9..aadc7dfb69d 100644 --- a/spec/support/helpers/usage_data_helpers.rb +++ b/spec/support/helpers/usage_data_helpers.rb @@ -110,7 +110,6 @@ module UsageDataHelpers gitaly database prometheus_metrics_enabled - web_ide_clientside_preview_enabled object_store topology ).freeze diff --git a/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb b/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb index 3a7588a5cc9..cc28a79b4ca 100644 --- a/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb +++ b/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb @@ -61,9 +61,14 @@ RSpec.shared_examples Repositories::GitHttpController do end it 'updates the user activity' do - expect_next_instance_of(Users::ActivityService) do |activity_service| - expect(activity_service).to receive(:execute) - end + activity_project = container.is_a?(PersonalSnippet) ? nil : project + + activity_service = instance_double(Users::ActivityService) + + args = { author: user, project: activity_project, namespace: activity_project&.namespace } + expect(Users::ActivityService).to receive(:new).with(args).and_return(activity_service) + + expect(activity_service).to receive(:execute) get :info_refs, params: params end diff --git a/yarn.lock b/yarn.lock index 7eb3bc2e9f5..6a2d6feafcd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1027,14 +1027,6 @@ resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.0.tgz#fe364f025ba74f6de6c837a84ef44bdb1d61e68f" integrity sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w== -"@codesandbox/sandpack-client@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@codesandbox/sandpack-client/-/sandpack-client-1.2.2.tgz#e0b79c52dcbc0b622f93527dc9ff3b163467e14a" - integrity sha512-sTPQVS7mzpEm2ttpHFFSqkGd1A1tBZn7UTZwIjBNCXKHywrt9o7MyrdhUuS03J7MyXN+HSJ55Vz+OGD1Wv4ejQ== - dependencies: - codesandbox-import-utils "^1.2.3" - lodash.isequal "^4.5.0" - "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -1083,15 +1075,15 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz#128b76ecb9be48b60cf5cfc1c63a4f00691a3239" integrity sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ== -"@eslint/eslintrc@^1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.3.tgz#2b044ab39fdfa75b4688184f9e573ce3c5b0ff95" - integrity sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg== +"@eslint/eslintrc@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" + integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== dependencies: ajv "^6.12.4" debug "^4.3.2" espree "^9.4.0" - globals "^13.15.0" + globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" @@ -1145,10 +1137,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.18.0.tgz#d89364feb42404a35824a54d518b51af8c1e900f" integrity sha512-ni9TmhusXpt/3k/DZzovMEUeB/6UTXiDpuujI8HDBqR4Mwlah6FBco5ZfolkW6YjFL0YvtcLWhnwZA0iM3hfMw== -"@gitlab/ui@54.1.1": - version "54.1.1" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-54.1.1.tgz#f95e51997b07011db319ed9cbd20b713b41cd224" - integrity sha512-yYvktCYM2xOzU2s8plMtnSFtCU9PIi5qBDSUAyyDspauIa95wvo79M1iVTwtfCZve+Qwr+vejxEF0GhqtVI8yA== +"@gitlab/ui@54.1.2": + version "54.1.2" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-54.1.2.tgz#c34ca7a34cb1c930e65435f993424f78f17aae50" + integrity sha512-CxtbFg6ULyzk1woLB+8ufOhgziPWVWgd5PMlRhQIWKR0WRfSa9tSii6qWa9vuUh9m8vs9SA9K1MjeLmaVrMB1A== dependencies: "@popperjs/core" "^2.11.2" bootstrap-vue "2.20.1" @@ -1342,14 +1334,14 @@ resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.0.tgz#0eee6373e11418bfe0b5638f654df7a4ca6a3950" integrity sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg== -"@humanwhocodes/config-array@^0.11.6": - version "0.11.6" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.6.tgz#6a51d603a3aaf8d4cf45b42b3f2ac9318a4adc4b" - integrity sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg== +"@humanwhocodes/config-array@^0.11.8": + version "0.11.8" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" + integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" - minimatch "^3.0.4" + minimatch "^3.0.5" "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" @@ -2912,15 +2904,15 @@ array-flatten@^2.1.2: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -array-includes@^3.1.4: - version "3.1.5" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" - integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== +array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" - get-intrinsic "^1.1.1" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" is-string "^1.0.7" array-union@^2.1.0: @@ -2933,14 +2925,24 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -array.prototype.flat@^1.2.5: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" - integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== +array.prototype.flat@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" + integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" arrify@^1.0.1: @@ -2989,6 +2991,11 @@ autosize@^5.0.1: resolved "https://registry.yarnpkg.com/autosize/-/autosize-5.0.1.tgz#ed269b0fa9b7eb47627048a1bb3299e99e003a0f" integrity sha512-UIWUlE4TOVPNNj2jjrU39wI4hEYbneUypEqcyRmRFIx5CC2gNdg3rQr+Zh7/3h6egbBvm33TDQjNQKtj9Tk1HA== +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + axios-mock-adapter@^1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-1.15.0.tgz#fbc06825d8302c95c3334d21023bba996255d45d" @@ -3168,11 +3175,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== -binaryextensions@2: - version "2.3.0" - resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.3.0.tgz#1d269cbf7e6243ea886aa41453c3651ccbe13c22" - integrity sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg== - bluebird@^3.1.1, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -3704,25 +3706,6 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -codesandbox-api@0.0.23: - version "0.0.23" - resolved "https://registry.yarnpkg.com/codesandbox-api/-/codesandbox-api-0.0.23.tgz#bf650a21b5f3c2369e03f0c19d10b4e2ba255b4f" - integrity sha512-fFGBkIghDkQILh7iHYlpZU5sfWncCDb92FQSFE4rR3VBcTfUsD5VZgpQi+JjZQuwWIdfl4cOhcIFrUYwshUezA== - -codesandbox-import-util-types@^1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/codesandbox-import-util-types/-/codesandbox-import-util-types-1.3.7.tgz#7a6097e248a75424d13b06b74368cd76bd2b3e10" - integrity sha512-8oP3emA0jyEuVOM2FBTpo/AF4C9vxHn14saVWZf2CQ/QhMtonBlNPE98ElrHkW+PFNXiO7Ad52Qr73b03n8qlA== - -codesandbox-import-utils@^1.2.3: - version "1.3.8" - resolved "https://registry.yarnpkg.com/codesandbox-import-utils/-/codesandbox-import-utils-1.3.8.tgz#5576786439c5f37ebd3fee5751e06027a1edef84" - integrity sha512-S12zO49QEkldoYLGh5KbkHRLOacg5BCNTue2vlyZXSpuK3oQdArwC/G1hCLKryV460bW3Ecn5xdkpfkUcFeOwQ== - dependencies: - codesandbox-import-util-types "^1.3.7" - istextorbinary "2.2.1" - lz-string "^1.4.4" - collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" @@ -4785,7 +4768,7 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -5130,11 +5113,6 @@ echarts@^5.3.2: tslib "2.3.0" zrender "5.3.2" -editions@^1.3.3: - version "1.3.4" - resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" - integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== - editorconfig@^0.15.3: version "0.15.3" resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" @@ -5252,34 +5230,53 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5: - version "1.20.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" - integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== +es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.20.4: + version "1.21.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" + integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== dependencies: + available-typed-arrays "^1.0.5" call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" function-bind "^1.1.1" function.prototype.name "^1.1.5" - get-intrinsic "^1.1.1" + get-intrinsic "^1.1.3" get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" has "^1.0.3" has-property-descriptors "^1.0.0" + has-proto "^1.0.1" has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" + internal-slot "^1.0.4" + is-array-buffer "^3.0.1" + is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" is-shared-array-buffer "^1.0.2" is-string "^1.0.7" + is-typed-array "^1.1.10" is-weakref "^1.0.2" - object-inspect "^1.12.0" + object-inspect "^1.12.2" object-keys "^1.1.1" - object.assign "^4.1.2" + object.assign "^4.1.4" regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" es-shim-unscopables@^1.0.0: version "1.0.0" @@ -5504,13 +5501,14 @@ eslint-import-resolver-jest@3.0.2: find-root "^1.1.0" resolve "^1.12.0" -eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== +eslint-import-resolver-node@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" + integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== dependencies: debug "^3.2.7" - resolve "^1.20.0" + is-core-module "^2.11.0" + resolve "^1.22.1" eslint-import-resolver-webpack@0.13.2: version "0.13.2" @@ -5529,13 +5527,12 @@ eslint-import-resolver-webpack@0.13.2: resolve "^1.20.0" semver "^5.7.1" -eslint-module-utils@^2.7.3: - version "2.7.3" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee" - integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== +eslint-module-utils@^2.7.4: + version "2.7.4" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" + integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== dependencies: debug "^3.2.7" - find-up "^2.1.0" eslint-plugin-babel@^5.3.0: version "5.3.0" @@ -5544,23 +5541,25 @@ eslint-plugin-babel@^5.3.0: dependencies: eslint-rule-composer "^0.3.0" -eslint-plugin-import@^2.26.0: - version "2.26.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" - integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== +eslint-plugin-import@^2.26.0, eslint-plugin-import@^2.27.5: + version "2.27.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" + integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== dependencies: - array-includes "^3.1.4" - array.prototype.flat "^1.2.5" - debug "^2.6.9" + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + array.prototype.flatmap "^1.3.1" + debug "^3.2.7" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.3" + eslint-import-resolver-node "^0.3.7" + eslint-module-utils "^2.7.4" has "^1.0.3" - is-core-module "^2.8.1" + is-core-module "^2.11.0" is-glob "^4.0.3" minimatch "^3.1.2" - object.values "^1.1.5" - resolve "^1.22.0" + object.values "^1.1.6" + resolve "^1.22.1" + semver "^6.3.0" tsconfig-paths "^3.14.1" eslint-plugin-jest@^27.0.4: @@ -5664,13 +5663,13 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@8.29.0: - version "8.29.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.29.0.tgz#d74a88a20fb44d59c51851625bc4ee8d0ec43f87" - integrity sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg== +eslint@8.32.0: + version "8.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.32.0.tgz#d9690056bb6f1a302bd991e7090f5b68fbaea861" + integrity sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ== dependencies: - "@eslint/eslintrc" "^1.3.3" - "@humanwhocodes/config-array" "^0.11.6" + "@eslint/eslintrc" "^1.4.1" + "@humanwhocodes/config-array" "^0.11.8" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" @@ -5689,7 +5688,7 @@ eslint@8.29.0: file-entry-cache "^6.0.1" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.15.0" + globals "^13.19.0" grapheme-splitter "^1.0.4" ignore "^5.2.0" import-fresh "^3.0.0" @@ -6063,13 +6062,6 @@ find-root@^1.1.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -6126,6 +6118,13 @@ follow-redirects@^1.0.0, follow-redirects@^1.14.4: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -6259,10 +6258,10 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" - integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -6392,13 +6391,20 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.15.0: - version "13.16.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.16.0.tgz#9be4aca28f311aaeb974ea54978ebbb5e35ce46a" - integrity sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q== +globals@^13.19.0: + version "13.19.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" + integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== dependencies: type-fest "^0.20.2" +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@^11.0.1, globby@^11.0.3, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -6423,6 +6429,13 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -6537,7 +6550,12 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" -has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -6997,12 +7015,12 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== +internal-slot@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" + integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== dependencies: - get-intrinsic "^1.1.0" + get-intrinsic "^1.1.3" has "^1.0.3" side-channel "^1.0.4" @@ -7045,6 +7063,15 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-array-buffer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" + integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -7089,10 +7116,10 @@ is-builtin-module@^3.1.0: dependencies: builtin-modules "^3.0.0" -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-ci@^2.0.0: version "2.0.0" @@ -7101,10 +7128,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.5.0, is-core-module@^2.7.0, is-core-module@^2.8.1, is-core-module@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== +is-core-module@^2.11.0, is-core-module@^2.5.0, is-core-module@^2.7.0, is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== dependencies: has "^1.0.3" @@ -7284,6 +7311,17 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -7382,15 +7420,6 @@ istanbul-reports@^3.0.0, istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -istextorbinary@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53" - integrity sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw== - dependencies: - binaryextensions "2" - editions "^1.3.3" - textextensions "2" - iterall@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" @@ -8098,14 +8127,6 @@ loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -8311,11 +8332,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lz-string@^1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" - integrity sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ== - make-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -9049,7 +9065,7 @@ minimatch@4.2.1: dependencies: brace-expansion "^1.1.7" -minimatch@^3.0.4, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -9475,10 +9491,10 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.12.0, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.12.2, object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== object-keys@^1.1.1: version "1.1.1" @@ -9492,14 +9508,14 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0, object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== +object.assign@^4.1.0, object.assign@^4.1.2, object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" object-keys "^1.1.1" object.entries@^1.1.5: @@ -9518,14 +9534,14 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.20.4" obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" @@ -9647,13 +9663,6 @@ p-limit@3.1.0, p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" -p-limit@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" - integrity sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng== - dependencies: - p-try "^1.0.0" - p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -9661,13 +9670,6 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -9704,11 +9706,6 @@ p-retry@^4.5.0: "@types/retry" "^0.12.0" retry "^0.13.1" -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -10665,7 +10662,7 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.9.0: +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.9.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -10772,6 +10769,15 @@ safe-buffer@5.2.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -11364,23 +11370,23 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" string_decoder@^1.0.0, string_decoder@^1.1.1, string_decoder@~1.1.1: version "1.1.1" @@ -11694,11 +11700,6 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -textextensions@2: - version "2.6.0" - resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.6.0.tgz#d7e4ab13fe54e32e08873be40d51b74229b00fc4" - integrity sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ== - three@^0.143.0: version "0.143.0" resolved "https://registry.yarnpkg.com/three/-/three-0.143.0.tgz#1455bca132cc2b20beb7f41d313e10c29e5ed9df" @@ -11983,6 +11984,15 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -12739,6 +12749,18 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" |