Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-04-03 15:11:40 +00:00
parent 79a05abe3d
commit e6120ad6ed
114 changed files with 2998 additions and 2317 deletions

View File

@ -49,7 +49,7 @@ build-gdk-image:
- .base-image-build-buildx
- .build-images:rules:build-gdk-image
tags:
- saas-linux-xlarge-amd64
- docker
stage: build-images
needs:
- job: retag-gdk-image

View File

@ -45,9 +45,11 @@ db:rollback single-db:
- .single-db
- .rails:rules:single-db
# https://docs.gitlab.com/ee/development/database/dbmigrate:multi-version-upgrade-job.html
db:migrate:multi-version-upgrade:
extends:
- .db-job-base
- .rails:rules:db:migrate:multi-version-upgrade
script:
- curl -o latest_upgrade_stop.gz https://gitlab.com/gitlab-org/quality/pg-dump-generator/-/raw/main/pg_dumps/ee/latest_upgrade_stop.gz
- gunzip -c latest_upgrade_stop.gz > gitlabhq_production
@ -55,7 +57,6 @@ db:migrate:multi-version-upgrade:
- apt-get update -qq && apt-get install -y -qq postgresql
- psql --output /dev/null -v "ON_ERROR_STOP=1" -h postgres -U postgres -d gitlabhq_test < gitlabhq_production
- bundle exec rake gitlab:db:configure
allow_failure: true
db:migrate:reset:
extends: .db-job-base

View File

@ -156,10 +156,10 @@
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_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")'
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-tag: &if-dot-com-gitlab-org-and-security-tag
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_COMMIT_TAG'
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org/security" && $CI_COMMIT_TAG'
.if-ruby-branch: &if-ruby-branch
if: '$CI_COMMIT_BRANCH =~ /^ruby\d+(_\d)*$/ || $CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby\d+(_\d)*/'
@ -1904,6 +1904,12 @@
- <<: *if-merge-request
changes: *decomposed-db-models-patterns
.rails:rules:db:migrate:multi-version-upgrade:
rules:
- if: '$DISABLE_DB_MULTI_VERSION_UPGRADE =~ /true|yes|1/i'
when: never
- !reference [".rails:rules:ee-and-foss-migration", rules]
.rails:rules:db-backup:
rules:
- <<: *if-merge-request-labels-pipeline-expedite

View File

@ -7,7 +7,7 @@ import {
GlKeysetPagination,
GlLoadingIcon,
} from '@gitlab/ui';
import { groupBy } from 'lodash';
import { uniqBy } from 'lodash';
import { s__ } from '~/locale';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
import { NEW_ROUTE_NAME } from '../constants';
@ -103,9 +103,7 @@ export default {
};
},
uniqueRecipients(userAchievements) {
return Object.entries(groupBy(userAchievements, 'user.id')).map(([, values]) => {
return values[0].user;
});
return uniqBy(userAchievements, 'user.id').map(({ user }) => user);
},
},
i18n: {

View File

@ -14,7 +14,7 @@ function initPopovers(elements) {
.catch(() => {});
}
// Render GitLab flavoured Markdown
// Render GitLab flavored Markdown
export function renderGFM(element) {
if (!element) {
return;
@ -25,7 +25,7 @@ export function renderGFM(element) {
'.js-render-kroki[hidden]',
'.js-render-math',
'.js-render-mermaid',
'[lang="json"][data-lang-params="table"]',
'[data-canonical-lang="json"][data-lang-params="table"]',
'.gfm-project_member',
'.gfm-issue, .gfm-work_item, .gfm-merge_request, .gfm-epic',
].map((selector) => Array.from(element.querySelectorAll(selector)));

View File

@ -261,8 +261,8 @@ export const GO_TO_PROJECT_FILES = {
defaultKeys: ['g f'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_FIND_FILE = {
id: 'project.goToFindFile',
export const START_SEARCH_PROJECT_FILE = {
id: 'project.startSearchFile',
description: __('Go to find file'),
defaultKeys: ['t'],
};
@ -588,7 +588,7 @@ const PROJECT_SHORTCUTS_GROUP = {
GO_TO_PROJECT_ACTIVITY_FEED,
GO_TO_PROJECT_RELEASES,
GO_TO_PROJECT_FILES,
GO_TO_PROJECT_FIND_FILE,
START_SEARCH_PROJECT_FILE,
GO_TO_PROJECT_COMMITS,
GO_TO_PROJECT_REPO_GRAPH,
GO_TO_PROJECT_REPO_CHARTS,

View File

@ -3,13 +3,14 @@ import { flatten } from 'lodash';
import Vue from 'vue';
import { Mousetrap, addStopCallback } from '~/lib/mousetrap';
import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils';
import { waitForElement } from '~/lib/utils/dom_utils';
import findAndFollowLink from '~/lib/utils/navigation_utility';
import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import {
keysFor,
TOGGLE_KEYBOARD_SHORTCUTS_DIALOG,
START_SEARCH,
START_SEARCH_PROJECT_FILE,
FOCUS_FILTER_BAR,
TOGGLE_PERFORMANCE_BAR,
HIDE_APPEARING_CONTENT,
@ -23,7 +24,6 @@ import {
GO_TO_YOUR_GROUPS,
GO_TO_MILESTONE_LIST,
GO_TO_YOUR_SNIPPETS,
GO_TO_PROJECT_FIND_FILE,
GO_TO_YOUR_REVIEW_REQUESTS,
} from './keybindings';
import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
@ -75,6 +75,7 @@ export default class Shortcuts {
this.addAll([
[TOGGLE_KEYBOARD_SHORTCUTS_DIALOG, this.onToggleHelp],
[START_SEARCH_PROJECT_FILE, Shortcuts.focusSearchFile],
[START_SEARCH, Shortcuts.focusSearch],
[FOCUS_FILTER_BAR, this.focusFilter.bind(this)],
[TOGGLE_PERFORMANCE_BAR, Shortcuts.onTogglePerfBar],
@ -98,13 +99,6 @@ export default class Shortcuts {
keysFor(TOGGLE_MARKDOWN_PREVIEW).includes(combo) ? false : undefined,
);
const findFileURL = document.body.dataset.findFile;
if (typeof findFileURL !== 'undefined' && findFileURL !== null) {
this.add(GO_TO_PROJECT_FIND_FILE, () => {
visitUrl(findFileURL);
});
}
$(document).on('click', '.js-shortcuts-modal-trigger', this.onToggleHelp);
if (shouldDisableShortcuts()) {
@ -263,6 +257,17 @@ export default class Shortcuts {
}
}
static async focusSearchFile(e) {
e?.preventDefault();
document.querySelector('#super-sidebar-search')?.click();
const searchInput = await waitForElement('#super-sidebar-search-modal #search');
if (!searchInput) return;
searchInput.value = '~';
searchInput.dispatchEvent(new Event('input'));
}
static hideAppearingContent(e) {
const elements = document.querySelectorAll('.tooltip, .popover');

View File

@ -66,9 +66,15 @@ export default {
type: String,
required: true,
},
allowRegistrationToken: {
type: Boolean,
required: false,
default: false,
},
registrationToken: {
type: String,
required: true,
required: false,
default: null,
},
},
data() {
@ -212,6 +218,7 @@ export default {
{{ s__('Runners|New instance runner') }}
</gl-button>
<registration-dropdown
:allow-registration-token="allowRegistrationToken"
:registration-token="registrationToken"
:type="$options.INSTANCE_TYPE"
placement="right"

View File

@ -7,6 +7,7 @@ import { provide } from 'ee_else_ce/ci/runner/admin_runners/provide';
import { visitUrl } from '~/lib/utils/url_utility';
import { updateOutdatedUrl } from '~/ci/runner/runner_search_utils';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import { createLocalState } from '../graphql/list/local_state';
import { showAlertFromLocalStorage } from '../local_storage_alert/show_alert_from_local_storage';
import AdminRunnersApp from './admin_runners_app.vue';
@ -32,7 +33,7 @@ export const initAdminRunners = (selector = '#js-admin-runners') => {
return null;
}
const { newRunnerPath, registrationToken } = el.dataset;
const { newRunnerPath, allowRegistrationToken, registrationToken } = el.dataset;
const { cacheConfig, typeDefs, localMutations } = createLocalState();
const apolloProvider = new VueApollo({
@ -50,6 +51,7 @@ export const initAdminRunners = (selector = '#js-admin-runners') => {
return h(AdminRunnersApp, {
props: {
newRunnerPath,
allowRegistrationToken: parseBoolean(allowRegistrationToken),
registrationToken,
},
});

View File

@ -5,8 +5,10 @@ import {
GlDisclosureDropdownItem,
GlDisclosureDropdownGroup,
GlIcon,
GlLink,
GlSprintf,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
import {
@ -21,30 +23,34 @@ import {
import RegistrationToken from './registration_token.vue';
import RegistrationTokenResetDropdownItem from './registration_token_reset_dropdown_item.vue';
const REGISTRATION_TOKEN_ENABLED = 'REGISTRATION_TOKEN_ENABLED';
const REGISTRATION_TOKEN_DISABLED = 'REGISTRATION_TOKEN_DISABLED';
const REGISTRATION_TOKEN_HIDDEN = 'REGISTRATION_TOKEN_HIDDEN';
export default {
i18n: {
showInstallationInstructions: s__(
'Runners|Show runner installation and registration instructions',
),
supportForRegistrationTokensDeprecated: s__(
'Runners|Support for registration tokens is deprecated',
),
},
components: {
GlDisclosureDropdown,
GlDisclosureDropdownItem,
GlDisclosureDropdownGroup,
GlDropdownForm,
GlIcon,
GlLink,
GlSprintf,
RegistrationToken,
RunnerInstructionsModal,
RegistrationTokenResetDropdownItem,
},
mixins: [glFeatureFlagMixin()],
props: {
allowRegistrationToken: {
type: Boolean,
required: false,
default: false,
},
registrationToken: {
type: String,
required: true,
required: false,
default: null,
},
type: {
type: String,
@ -72,6 +78,23 @@ export default {
return I18N_REGISTER_RUNNER;
}
},
isRegistrationTokenPresent() {
return Boolean(this.registrationToken);
},
state() {
if (this.registrationToken && this.allowRegistrationToken) {
// Legacy registration with registration token can be used, will be fully removed by 18.0
return REGISTRATION_TOKEN_ENABLED;
}
if (!this.allowRegistrationToken) {
// If registration is disabled by admins or group owners, display the dropdown with a message
return REGISTRATION_TOKEN_DISABLED;
}
// If registration is still enabled for the instance or group, but the user cannot see the
// token due to permissions, hide this control as they don't have access
return REGISTRATION_TOKEN_HIDDEN;
},
},
methods: {
onShowInstructionsClick() {
@ -86,11 +109,18 @@ export default {
this.$refs.runnerRegistrationDropdown.close();
},
},
REGISTRATION_TOKEN_ENABLED,
REGISTRATION_TOKEN_DISABLED,
REGISTRATION_TOKEN_HIDDEN,
registrationTokenDisabledHelpPagePath: helpPagePath('ci/runners/new_creation_workflow.html', {
anchor: 'using-registration-tokens-after-gitlab-170',
}),
};
</script>
<template>
<gl-disclosure-dropdown
v-if="state !== $options.REGISTRATION_TOKEN_HIDDEN"
ref="runnerRegistrationDropdown"
:toggle-text="actionText"
toggle-class="gl-px-3!"
@ -101,30 +131,48 @@ export default {
text-sr-only
no-caret
>
<gl-dropdown-form class="gl-p-4!">
<registration-token input-id="token-value" :value="currentRegistrationToken" @copy="onCopy">
<template #label-description>
<gl-icon name="warning" class="gl-text-orange-500" />
<span class="gl-text-secondary">
{{ $options.i18n.supportForRegistrationTokensDeprecated }}
</span>
</template>
</registration-token>
</gl-dropdown-form>
<gl-disclosure-dropdown-group bordered>
<gl-disclosure-dropdown-item @action="onShowInstructionsClick">
<template #list-item>
{{ $options.i18n.showInstallationInstructions }}
<runner-instructions-modal
ref="runnerInstructionsModal"
:registration-token="currentRegistrationToken"
data-testid="runner-instructions-modal"
/>
</template>
</gl-disclosure-dropdown-item>
</gl-disclosure-dropdown-group>
<gl-disclosure-dropdown-group bordered>
<registration-token-reset-dropdown-item :type="type" @tokenReset="onTokenReset" />
</gl-disclosure-dropdown-group>
<div v-if="state == $options.REGISTRATION_TOKEN_DISABLED" class="gl-px-4 gl-py-2">
<gl-icon name="error" class="gl-text-red-500" />
<gl-sprintf
:message="
s__(
'Runners|Creating runners with runner registration tokens is disabled. %{linkStart}Learn more%{linkEnd}.',
)
"
>
<template #link="{ content }"
><gl-link :href="$options.registrationTokenDisabledHelpPagePath">{{
content
}}</gl-link></template
>
</gl-sprintf>
</div>
<template v-if="state == $options.REGISTRATION_TOKEN_ENABLED">
<gl-dropdown-form class="gl-p-4!">
<registration-token input-id="token-value" :value="currentRegistrationToken" @copy="onCopy">
<template #label-description>
<gl-icon name="warning" class="gl-text-orange-500" />
<span class="gl-text-secondary">
{{ s__('Runners|Support for registration tokens is deprecated') }}
</span>
</template>
</registration-token>
</gl-dropdown-form>
<gl-disclosure-dropdown-group bordered>
<gl-disclosure-dropdown-item @action="onShowInstructionsClick">
<template #list-item>
{{ s__('Runners|Show runner installation and registration instructions') }}
<runner-instructions-modal
ref="runnerInstructionsModal"
:registration-token="currentRegistrationToken"
data-testid="runner-instructions-modal"
/>
</template>
</gl-disclosure-dropdown-item>
</gl-disclosure-dropdown-group>
<gl-disclosure-dropdown-group bordered>
<registration-token-reset-dropdown-item :type="type" @tokenReset="onTokenReset" />
</gl-disclosure-dropdown-group>
</template>
</gl-disclosure-dropdown>
</template>

View File

@ -65,6 +65,11 @@ export default {
required: false,
default: null,
},
allowRegistrationToken: {
type: Boolean,
required: false,
default: false,
},
registrationToken: {
type: String,
required: false,
@ -223,7 +228,7 @@ export default {
{{ s__('Runners|New group runner') }}
</gl-button>
<registration-dropdown
v-if="registrationToken"
:allow-registration-token="allowRegistrationToken"
:registration-token="registrationToken"
:type="$options.GROUP_TYPE"
placement="right"

View File

@ -2,6 +2,7 @@ import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import { createLocalState } from '../graphql/list/local_state';
import GroupRunnersApp from './group_runners_app.vue';
@ -16,6 +17,7 @@ export const initGroupRunners = (selector = '#js-group-runners') => {
}
const {
allowRegistrationToken,
registrationToken,
runnerInstallHelpPage,
newRunnerPath,
@ -44,9 +46,10 @@ export const initGroupRunners = (selector = '#js-group-runners') => {
render(h) {
return h(GroupRunnersApp, {
props: {
registrationToken,
groupFullPath,
newRunnerPath,
allowRegistrationToken: parseBoolean(allowRegistrationToken),
registrationToken,
},
});
},

View File

@ -3,6 +3,7 @@ import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import RegistrationDropdown from '~/ci/runner/components/registration/registration_dropdown.vue';
import { PROJECT_TYPE } from '~/ci/runner/constants';
import { parseBoolean } from '~/lib/utils/common_utils';
Vue.use(VueApollo);
@ -15,7 +16,7 @@ export const initProjectRunnersRegistrationDropdown = (
return null;
}
const { registrationToken, projectId } = el.dataset;
const { allowRegistrationToken, registrationToken, projectId } = el.dataset;
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
@ -30,6 +31,7 @@ export const initProjectRunnersRegistrationDropdown = (
render(h) {
return h(RegistrationDropdown, {
props: {
allowRegistrationToken: parseBoolean(allowRegistrationToken),
registrationToken,
type: PROJECT_TYPE,
},

View File

@ -140,6 +140,11 @@ export default {
return !this.propsSource.editable;
},
},
watch: {
model(newValue) {
this.$emit('update', newValue);
},
},
created() {
if (this.isNonEmptyPassword) {
this.model = null;

View File

@ -40,6 +40,7 @@ export default {
v-bind="field"
:field-class="fieldClass"
:is-validated="isValidated"
@update="$emit('update', { value: $event, field })"
/>
</div>
</template>

View File

@ -1,4 +1,5 @@
import { has } from 'lodash';
import { __ } from '~/locale';
import { isInIssuePage, isInMRPage, isInEpicPage } from './common_utils';
/**
@ -139,3 +140,39 @@ export const replaceCommentsWith = (el, tagName) => {
commentNode = iterator.nextNode();
}
};
/**
* Wait for an element to become available in the DOM
* @param {String} selector - the query selector for the target element
* @param {Number} timeoutDelay - how long to wait before timing out
* @returns {Promise} A promise that resolves when the element becomes available
*/
export const waitForElement = (selector, timeoutDelay = 5000) =>
new Promise((resolve, reject) => {
let element;
const findElement = () => {
// Set `element` here to prevent unnecessary DOM lookups
if (!element) element = document.querySelector(selector);
return element;
};
if (findElement()) {
resolve(findElement());
} else {
let timeout;
const observer = new MutationObserver(() => {
if (findElement()) {
observer.disconnect();
clearTimeout(timeout);
resolve(findElement());
}
});
observer.observe(document.body, { childList: true, subtree: true });
timeout = setTimeout(() => {
observer.disconnect();
reject(__('Timeout: Element not found'));
}, timeoutDelay); // disconnect if no element was found
}
});

View File

@ -1,6 +1,7 @@
import Vue from 'vue';
import { addShortcutsExtension } from '~/behaviors/shortcuts';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import { initFindFileShortcut } from '~/projects/behaviors';
import initClustersDeprecationAlert from '~/projects/clusters_deprecation_alert';
import leaveByUrl from '~/namespaces/leave_by_url';
import initTerraformNotification from '~/projects/terraform_notification';
@ -82,3 +83,4 @@ const initCodeDropdown = () => {
initCodeDropdown();
initSourceCodeDropdowns();
initFindFileShortcut();

View File

@ -2,6 +2,7 @@ import $ from 'jquery';
import initTree from 'ee_else_ce/repository';
import { addShortcutsExtension } from '~/behaviors/shortcuts';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import { initFindFileShortcut } from '~/projects/behaviors';
import NewCommitForm from '~/new_commit_form';
import initAmbiguousRefModal from '~/ref/init_ambiguous_ref_modal';
@ -9,3 +10,4 @@ new NewCommitForm($('.js-create-dir-form')); // eslint-disable-line no-new
initTree();
initAmbiguousRefModal();
addShortcutsExtension(ShortcutsNavigation);
initFindFileShortcut();

View File

@ -0,0 +1,7 @@
import Shortcuts from '~/behaviors/shortcuts/shortcuts';
export const initFindFileShortcut = () => {
const findFileButton = document.querySelector('.shortcuts-find-file');
if (!findFileButton) return;
findFileButton.addEventListener('click', Shortcuts.focusSearchFile);
};

View File

@ -4,13 +4,14 @@ import { __ } from '~/locale';
import { createAlert } from '~/alert';
import getRefMixin from '~/repository/mixins/get_ref';
import initSourcegraph from '~/sourcegraph';
import Shortcuts from '~/behaviors/shortcuts/shortcuts';
import { addShortcutsExtension } from '~/behaviors/shortcuts';
import { shouldDisableShortcuts } from '~/behaviors/shortcuts/shortcuts_toggle';
import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob';
import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
import {
keysFor,
GO_TO_PROJECT_FIND_FILE,
START_SEARCH_PROJECT_FILE,
PROJECT_FILES_GO_TO_PERMALINK,
} from '~/behaviors/shortcuts/keybindings';
import { sanitize } from '~/lib/dompurify';
@ -98,10 +99,10 @@ export default {
return !this.blobInfo.storedExternally && this.blobInfo.externalStorage !== 'lfs';
},
findFileShortcutKey() {
return keysFor(GO_TO_PROJECT_FIND_FILE)[0];
return keysFor(START_SEARCH_PROJECT_FILE)[0];
},
findFileTooltip() {
const { description } = GO_TO_PROJECT_FIND_FILE;
const { description } = START_SEARCH_PROJECT_FILE;
const key = this.findFileShortcutKey;
return shouldDisableShortcuts()
? null
@ -150,6 +151,9 @@ export default {
document.querySelectorAll('.js-data-file-blob-permalink-url, .js-blob-blame-link'),
);
},
handleFindFile() {
Shortcuts.focusSearchFile();
},
},
};
</script>
@ -160,8 +164,8 @@ export default {
v-gl-tooltip.html="findFileTooltip"
:aria-keyshortcuts="findFileShortcutKey"
data-testid="find"
:href="blobInfo.findFilePath"
:class="$options.buttonClassList"
@click="handleFindFile"
>
{{ $options.i18n.findFile }}
</gl-button>

View File

@ -2,6 +2,7 @@
// eslint-disable-next-line no-restricted-imports
import { mapState, mapGetters } from 'vuex';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ScopeSidebarNavigation from '~/search/sidebar/components/scope_sidebar_navigation.vue';
import SidebarPortal from '~/super_sidebar/components/sidebar_portal.vue';
import { toggleSuperSidebarCollapsed } from '~/super_sidebar/super_sidebar_collapsed_state_manager';
@ -47,6 +48,7 @@ export default {
MilestonesFilters,
AllScopesStartFilters,
},
mixins: [glFeatureFlagsMixin()],
computed: {
...mapState(['searchType']),
...mapGetters(['currentScope']),
@ -57,7 +59,9 @@ export default {
return this.searchType === SEARCH_TYPE_ADVANCED;
},
isZoektSearch() {
return this.searchType === SEARCH_TYPE_ZOEKT;
return (
this.searchType === SEARCH_TYPE_ZOEKT && this.glFeatures.searchAddArchivedFilterToZoekt
);
},
showIssuesFilters() {
return this.currentScope === SCOPE_ISSUES;

View File

@ -80,7 +80,7 @@ export default {
},
computed: {
issuableId() {
return getIdFromGraphQLId(this.issuable.id);
return getIdFromGraphQLId(this.issuable.id) || this.issuable.id;
},
issuableIid() {
return this.issuable.iid;

View File

@ -10,7 +10,9 @@ class Groups::RunnersController < Groups::ApplicationController
urgency :low
def index
@allow_registration_token = @group.allow_runner_registration_token?
@group_runner_registration_token = @group.runners_token if can?(current_user, :register_group_runners, group)
@group_new_runner_path = new_group_runner_path(@group) if can?(current_user, :create_runner, group)
Gitlab::Tracking.event(self.class.name, 'index', user: current_user, namespace: @group)

View File

@ -66,3 +66,5 @@ module Mutations
end
end
end
Mutations::MergeRequests::Update.prepend_mod_with('Mutations::MergeRequests::Update')

View File

@ -17,6 +17,10 @@ module Types
value 'INACTIVE',
value: 'inactive',
description: 'Mergeability check is disabled via settings.'
value 'WARNING',
value: 'warning',
description: 'Mergeability check has passed with a warning.'
end
end
end

View File

@ -59,6 +59,7 @@ module Ci
# https://gitlab.com/gitlab-org/gitlab-runner
runner_install_help_page: 'https://docs.gitlab.com/runner/install/',
new_runner_path: new_admin_runner_path,
allow_registration_token: Gitlab::CurrentSettings.allow_runner_registration_token.to_s,
registration_token: Gitlab::CurrentSettings.runners_registration_token,
online_contact_timeout_secs: ::Ci::Runner::ONLINE_CONTACT_TIMEOUT.to_i,
stale_timeout_secs: ::Ci::Runner::STALE_TIMEOUT.to_i,

View File

@ -501,6 +501,8 @@ module ApplicationSettingImplementation
end
def runners_registration_token
return unless Gitlab::CurrentSettings.allow_runner_registration_token
ensure_runners_registration_token!
end

View File

@ -776,6 +776,8 @@ class Group < Namespace
# we do this on read since migrating all existing groups is not a feasible
# solution.
def runners_token
return unless allow_runner_registration_token?
ensure_runners_token!
end

View File

@ -2249,6 +2249,8 @@ class Project < ApplicationRecord
end
def runners_token
return unless namespace.allow_runner_registration_token?
ensure_runners_token!
end

View File

@ -24,7 +24,7 @@ class SystemNoteMetadata < ApplicationRecord
opened closed merged duplicate locked unlocked outdated reviewer
tag due_date start_date_or_due_date pinned_embed cherry_pick health_status approved unapproved
status alert_issue_added relate unrelate new_alert_added severity contact timeline_event
issue_type relate_to_child unrelate_from_child relate_to_parent unrelate_from_parent
issue_type relate_to_child unrelate_from_child relate_to_parent unrelate_from_parent override
].freeze
validates :note, presence: true, unless: :importing?

View File

@ -110,6 +110,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
@subject.runner_registration_enabled?
end
condition(:runner_registration_token_enabled, scope: :subject) do
@subject.allow_runner_registration_token?
end
condition(:raise_admin_package_to_owner_enabled) do
Feature.enabled?(:raise_group_admin_package_permission_to_owner, @subject)
end
@ -375,6 +379,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
prevent :create_runner
end
rule { ~runner_registration_token_enabled }.policy do
prevent :register_group_runners
end
rule { migration_bot }.policy do
enable :read_resource_access_tokens
enable :destroy_resource_access_tokens

View File

@ -0,0 +1,41 @@
# frozen_string_literal: true
module Ci
module Components
module Usages
class CreateService
def initialize(component, used_by_project:)
@component = component
@used_by_project = used_by_project
end
def execute
component_usage = Ci::Catalog::Resources::Components::Usage.new(
component: component,
catalog_resource: component.catalog_resource,
project: component.project,
used_by_project_id: used_by_project.id
)
if component_usage.valid?
component_usage.save
return ServiceResponse.success(message: 'Usage recorded')
end
errors = component_usage.errors
if errors.size == 1 && errors.first.type == :taken # Only unique validation failed
ServiceResponse.success(message: 'Usage already recorded for today')
else
ServiceResponse.error(message: errors.full_messages.join(', '))
end
end
private
attr_reader :component, :used_by_project
end
end
end
end

View File

@ -53,6 +53,8 @@ module Ci
strong_memoize_attr :attrs_from_token
def registration_token_allowed?(attrs)
return false if registration_token.nil?
case attrs[:runner_type]
when :group_type
token_scope.allow_runner_registration_token?
@ -64,6 +66,8 @@ module Ci
end
def runner_registration_token_valid?(registration_token)
return false if registration_token.nil?
ActiveSupport::SecurityUtils.secure_compare(registration_token, Gitlab::CurrentSettings.runners_registration_token)
end

View File

@ -49,6 +49,11 @@ module MergeRequests
.inactive(payload: default_payload(args))
end
def warning(**args)
Gitlab::MergeRequests::Mergeability::CheckResult
.warning(payload: default_payload(args))
end
def default_payload(args)
args.merge(identifier: self.class.identifier)
end

View File

@ -15,13 +15,13 @@
%h5
= s_('Runners|Runner registration')
%span.form-text.gl-mb-3.gl-mt-0
= s_('Runners|If both settings are disabled, new runners cannot be registered.')
= link_to _('Learn more.'), help_page_path('administration/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer'
= hidden_field_tag "application_setting[valid_runner_registrars][]", nil
- ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES.each do |type|
= f.gitlab_ui_checkbox_component :valid_runner_registrars, s_("Runners|Members of the %{type} can register runners") % { type: type },
checkbox_options: { multiple: true, checked: valid_runner_registrars.include?(type) },
checked_value: type,
unchecked_value: nil
= f.gitlab_ui_checkbox_component :allow_runner_registration_token, s_("AdminSettings|Allow runner registration token"), help_text: s_("AdminSettings|When disabled, runner registration tokens are disabled from runner pages, and maintainers and owners cannot use registration tokens to register runners. They can use runner authentication tokens instead as the more secure runner registration method.")
= hidden_field_tag "application_setting[valid_runner_registrars][]", nil
- ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES.each do |type|
= f.gitlab_ui_checkbox_component :valid_runner_registrars, s_("Runners|Members of the %{type} can create runners") % { type: type },
checkbox_options: { multiple: true, checked: valid_runner_registrars.include?(type) },
checked_value: type,
unchecked_value: nil
= f.submit _('Save changes'), pajamas_button: true

View File

@ -1,3 +1,3 @@
- page_title s_('Runners|Runners')
#js-group-runners{ data: group_runners_data_attributes(@group).merge({ registration_token: @group_runner_registration_token, new_runner_path: @group_new_runner_path }) }
#js-group-runners{ data: group_runners_data_attributes(@group).merge({ allow_registration_token: @allow_registration_token.to_s, registration_token: @group_runner_registration_token, new_runner_path: @group_new_runner_path }) }

View File

@ -1,9 +1,3 @@
- find_file_description = _('Go to find file')
- find_file_shortcut = 't'
- find_file_title = "#{find_file_description} <kbd class='flat ml-1' aria-hidden=true>#{find_file_shortcut}</kbd>"
= link_button_to _('Find file'), project_find_file_path(@project, @ref, ref_type: @ref_type),
'aria-keyshortcuts': find_file_shortcut,
class: 'has-tooltip shortcuts-find-file',
'data-html': true,
title: find_file_title,
rel: 'nofollow'
- find_file_title = "Go to file, press <kbd class='flat ml-1' aria-hidden=true>/~</kbd> or <kbd class='flat ml-1' aria-hidden=true>t</kbd>"
= render Pajamas::ButtonComponent.new(button_options: { class: 'has-tooltip shortcuts-find-file', title: find_file_title, 'aria-keyshortcuts': "/+~ t", 'data-html': true }) do
= _('Find file')

View File

@ -8,7 +8,11 @@
= render Pajamas::ButtonComponent.new(href: new_project_runner_path(@project), variant: :confirm) do
= s_('Runners|New project runner')
.gl-display-inline
#js-project-runner-registration-dropdown{ data: { registration_token: @project.runners_token, project_id: @project.id } }
#js-project-runner-registration-dropdown{ data: {
allow_registration_token: @project.namespace.allow_runner_registration_token?.to_s,
registration_token: @project.runners_token,
project_id: @project.id
} }
- else
= _('Please contact an admin to create runners.')
= link_to _('Learn more.'), help_page_path('administration/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer'

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/430037
milestone: '16.7'
type: development
group: group::pipeline authoring
default_enabled: false
default_enabled: true

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
# Even though `ActionView::Helpers::AssetTagHelper.preload_links_header`
# is set to false, `preload_link_tag` sends the Link header if the total
# header size to send is under 8K. However, this causes HTTP responses
# to fail in NGINX if the default `proxy_buffer_size` is set too low.
#
# Ironically because `app/views/layouts/_loading_hints.html.haml` is a
# cached partial, `preload_link_tag` generates the HTML, but only
# actually sends the `Link` header once a minute when the cache expires.
# This suggests that the `Link` header isn't really helping much, and it
# causes more trouble than it's worth.
#
# Rails 7.1 lowered the `preload_link_tag` limit to 1000 bytes in
# https://github.com/rails/rails/pull/48405, but that may not be
# sufficient.
#
# https://github.com/rails/rails/issues/51436 proposes to disable the
# sending of the Link header entirely. This patch does this by turning
# send_preload_links_header into a NOP.
#
# We can probably drop this patch for Rails 7.1 and up, but we might
# want to wait for https://github.com/rails/rails/pull/51441 or some
# mechanism that can disable the `Link` header.
if Gem::Version.new(ActionView.version) >= Gem::Version.new('7.1')
raise 'New version of ActionView detected. This patch can likely be removed.'
end
require "action_view/helpers/asset_tag_helper"
module ActionView
module Helpers
module AssetTagHelper
def send_preload_links_header(preload_links, max_header_size: MAX_HEADER_SIZE); end
end
end
end

View File

@ -4,7 +4,8 @@ classes:
- BulkImport
feature_categories:
- importers
description: Used to store and track the status of a bulk import request of groups or projects
description: Used to store and track the status of a bulk import request of groups
or projects
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42978
milestone: '13.5'
gitlab_schema: gitlab_main
gitlab_schema: gitlab_main_clusterwide

View File

@ -7,4 +7,19 @@ feature_categories:
description: Persists error event data for the Error Tracking's GitLab backend
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64712
milestone: '14.1'
gitlab_schema: gitlab_main
gitlab_schema: gitlab_main_cell
allow_cross_joins:
- gitlab_main_clusterwide
allow_cross_transactions:
- gitlab_main_clusterwide
allow_cross_foreign_keys:
- gitlab_main_clusterwide
desired_sharding_key:
project_id:
references: projects
backfill_via:
parent:
foreign_key: error_id
table: error_tracking_errors
sharding_key: project_id
belongs_to: error

View File

@ -7,4 +7,4 @@ feature_categories:
description: Text templates used to populate comments using a quick action
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80807
milestone: '14.9'
gitlab_schema: gitlab_main
gitlab_schema: gitlab_main_clusterwide

View File

@ -7,4 +7,19 @@ feature_categories:
description: Persists issue data for the Error Tracking's Sentry backend
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20629
milestone: '12.6'
gitlab_schema: gitlab_main
gitlab_schema: gitlab_main_cell
allow_cross_joins:
- gitlab_main_clusterwide
allow_cross_transactions:
- gitlab_main_clusterwide
allow_cross_foreign_keys:
- gitlab_main_clusterwide
desired_sharding_key:
namespace_id:
references: namespaces
backfill_via:
parent:
foreign_key: issue_id
table: issues
sharding_key: namespace_id
belongs_to: issue

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class AddOverrideChangesRequestedToMergeRequest < Gitlab::Database::Migration[2.2]
enable_lock_retries!
milestone '16.11'
def change
add_column :merge_requests, :override_requested_changes, :boolean, default: false, null: false
end
end

View File

@ -0,0 +1 @@
4df10234f382af204774214a1eaf7bbfc8d231ab8571ccf10b4fdc2caaedc9e5

View File

@ -11253,6 +11253,7 @@ CREATE TABLE merge_requests (
draft boolean DEFAULT false NOT NULL,
prepared_at timestamp with time zone,
merged_commit_sha bytea,
override_requested_changes boolean DEFAULT false NOT NULL,
CONSTRAINT check_970d272570 CHECK ((lock_version IS NOT NULL))
);

View File

@ -153,10 +153,6 @@ The payload is available in the [Metrics and profiling](#manually-upload-service
### Through the configuration file
NOTE:
The method to disable Service Ping in the GitLab configuration file does not work in
GitLab versions 9.3 to 13.12.3. For more information about how to disable it, see [troubleshooting](../../development/internal_analytics/service_ping/troubleshooting.md#cannot-disable-service-ping-with-the-configuration-file).
To disable Service Ping and prevent it from being configured in the future through
the Admin Area.
@ -209,9 +205,6 @@ For an example payload, see [Example Service Ping payload](../../development/int
## Manually upload Service Ping payload
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7388) in GitLab 14.8 with a flag named `admin_application_settings_service_usage_data_center`. Disabled by default.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83265) in GitLab 14.10.
You can upload the Service Ping payload to GitLab even if your instance doesn't have internet access,
or if the Service Ping [cron job](../../development/internal_analytics/service_ping/index.md#how-service-ping-works) is not enabled.

View File

@ -10,8 +10,6 @@ DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34940) in GitLab 12.7.
## Error Tracking project settings
The project settings API allows you to retrieve the [Error Tracking](../operations/error_tracking.md)
@ -63,7 +61,7 @@ Supported attributes:
| ------------ | ------- |----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer | yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) owned by the authenticated user. |
| `active` | boolean | yes | Pass `true` to enable the error tracking setting configuration or `false` to disable it. |
| `integrated` | boolean | yes | Pass `true` to enable the integrated error tracking backend. [Available in](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68260) GitLab 14.2 and later. |
| `integrated` | boolean | yes | Pass `true` to enable the integrated error tracking backend. |
Example request:
@ -96,7 +94,7 @@ PATCH /projects/:id/error_tracking/settings
| ------------ | ------- | -------- | --------------------- |
| `id` | integer | yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) owned by the authenticated user. |
| `active` | boolean | yes | Pass `true` to enable the already configured error tracking settings or `false` to disable it. |
| `integrated` | boolean | no | Pass `true` to enable the integrated error tracking backend. [Available in](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68260) GitLab 14.2 and later. |
| `integrated` | boolean | no | Pass `true` to enable the integrated error tracking backend. |
```shell
curl --request PATCH --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/error_tracking/settings?active=true"
@ -116,8 +114,6 @@ Example response:
## Error Tracking client keys
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68384) in GitLab 14.3.
For [integrated error tracking](https://gitlab.com/gitlab-org/gitlab/-/issues/329596) feature. Only for users with the
Maintainer role for the project.

View File

@ -6079,6 +6079,7 @@ Input type: `MergeRequestUpdateInput`
| <a id="mutationmergerequestupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationmergerequestupdatedescription"></a>`description` | [`String`](#string) | Description of the merge request (Markdown rendered as HTML for caching). |
| <a id="mutationmergerequestupdateiid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
| <a id="mutationmergerequestupdateoverriderequestedchanges"></a>`overrideRequestedChanges` | [`Boolean`](#boolean) | Override all requested changes. Can only be set by users who have permissionto merge this merge request. |
| <a id="mutationmergerequestupdateprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
| <a id="mutationmergerequestupdatestate"></a>`state` | [`MergeRequestNewState`](#mergerequestnewstate) | Action to perform to change the state. |
| <a id="mutationmergerequestupdatetargetbranch"></a>`targetBranch` | [`String`](#string) | Target branch of the merge request. |
@ -32467,6 +32468,7 @@ Representation of whether a mergeability check passed, failed or is inactive.
| <a id="mergeabilitycheckstatusfailed"></a>`FAILED` | Mergeability check has failed. The merge request cannot be merged. |
| <a id="mergeabilitycheckstatusinactive"></a>`INACTIVE` | Mergeability check is disabled via settings. |
| <a id="mergeabilitycheckstatussuccess"></a>`SUCCESS` | Mergeability check has passed. |
| <a id="mergeabilitycheckstatuswarning"></a>`WARNING` | Mergeability check has passed with a warning. |
### `MilestoneSort`

View File

@ -46,8 +46,6 @@ Example response:
## Export metric definitions as a single YAML file
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57270) in GitLab 13.11.
Export all metric definitions as a single YAML file, similar to the [Metrics Dictionary](https://metrics.gitlab.com/), for easier importing.
```plaintext

View File

@ -42,6 +42,8 @@ This bulkhead can be used as a launching pad for a full data restore from `us-ea
### Select an alternate region
We are going with **`us-central1`**. Discussion for this was done in <https://gitlab.com/gitlab-com/gl-infra/production-engineering/-/issues/25094>
- Dependencies: none
- Teams: Ops

View File

@ -590,4 +590,4 @@ This GitLab CI configuration is invalid: component 'gitlab.com/my-namespace/my-p
```
The `~latest` behavior [was updated](https://gitlab.com/gitlab-org/gitlab/-/issues/442238)
in GitLab 16.11. It now refers to the latest semantic version of the catalog resource. To resolve this issue, [create a new release](#publish-a-new-release).
in GitLab 16.10. It now refers to the latest semantic version of the catalog resource. To resolve this issue, [create a new release](#publish-a-new-release).

View File

@ -3975,10 +3975,7 @@ test:
#### `retry:exit_codes`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/430037) in GitLab 16.10 [with a flag](../../administration/feature_flags.md) named `ci_retry_on_exit_codes`. Disabled by default.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available,
an administrator can [enable the feature flag](../../administration/feature_flags.md) named `ci_retry_on_exit_codes`.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/430037) in GitLab 16.11.
Use `retry:exit_codes` with `retry:max` to retry jobs for only specific failure cases.
`retry:max` is the maximum number of retries, like [`retry`](#retry), and can be

View File

@ -145,21 +145,23 @@ GITLAB_SIMULATE_SAAS=1 RAILS_ENV=development bundle exec rake 'gitlab:duo:setup[
1. Ensure you have followed [the process to obtain an EE license](https://handbook.gitlab.com/handbook/developer-onboarding/#working-on-gitlab-ee-developer-licenses) for your local instance and you applied Ultimate license.
1. To verify that the license is applied go to **Admin Area** > **Subscription** and check the subscription plan.
1. Allow use of EE features for your instance.
1. Go to **Admin Area** > **Settings** > **General** -> **Account and limit**
1. Enable **Allow use of licensed EE features**
1. Go to **Admin Area > Settings > General**.
1. Expand the **Account and limit** section.
1. Enable **Allow use of licensed EE features**.
1. Simulate the GDK to [simulate SaaS](../ee_features.md#simulate-a-saas-instance).
1. Ensure the group you want to test has an Ultimate license.
1. Go to **Admin Area** > **Overview** > **Groups**
1. Go to **Admin Area > Overview > Groups**.
1. Select **Edit** for your chosen group.
1. Go to **Permissions and group features**
1. Go to **Permissions and group features**.
1. Choose *Ultimate* from the **Plan** list.
1. Enable `Experiment & Beta features` for your group.
1. Go to the group with the Ultimate license
1. **Group Settings** > **General** -> **Permissions and group features**
1. Enable **Experiment & Beta features**
1. Enable the specific feature flag for the feature you want to test
1. You can use Rake task `rake gitlab:duo:enable_feature_flags` to enable all feature flags that are assigned to group AI Framework
1. Setup [AI Gateway](#local-setup)
1. Go to the group with the Ultimate license.
1. Select **Settings > General**.
1. Expand the **Permissions and group features** section.
1. Enable **Experiment & Beta features**.
1. Enable the specific feature flag for the feature you want to test.
1. You can use Rake task `rake gitlab:duo:enable_feature_flags` to enable all feature flags that are assigned to group AI Framework.
1. Setup [AI Gateway](#local-setup).
### Bypass AI Gateway

View File

@ -101,6 +101,7 @@ To add a new feature bound to a scope:
token as a scope.
<!-- markdownlint-disable proper-names -->
`backend` is the targeted backend service and will become the token audience.
`service_start_time` is the cut-off date after which payment for this feature is required.

View File

@ -0,0 +1,41 @@
---
stage: Data Stores
group: Database
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
---
# db:migrate:multi-version-upgrade job
> - [Introduced](https://gitlab.com/groups/gitlab-org/quality/quality-engineering/-/epics/19) in GitLab 16.11.
This job runs on the test stage of a merge request pipeline. It validates that migrations pass
for multi-version upgrade from the latest [required upgrade stop](../../update/index.md#required-upgrade-stops)
to the author's working branch. It achieves it by running `gitlab:db:configure` against PostgreSQL
dump created from the latest known [GitLab version stop](../../update/index.md#upgrade-paths) with test data.
The database dump is generated and maintained with [PostgreSQL Dump Generator](https://gitlab.com/gitlab-org/quality/pg-dump-generator).
To seed database with data, the tool uses Data Seeder with [`bulk_data.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/db/seeds/data_seeder/bulk_data.rb)
configuration to seed all factories and uses `db:seed_fu` to seed all [`db/fixtures`](../development_seed_files.md).
Latest dump is generated automatically in scheduled pipelines for the latest patch
release of the required stop.
## Troubleshooting
### Database reconfigure failures
This failure usually happens due to an actual migration error in your working branch.
To reproduce the failure locally follow [Migration upgrade testing](https://gitlab.com/gitlab-org/quality/pg-dump-generator#migration-upgrade-testing)
guidance. It outlines the steps how to import the latest PostgreSQL dump
in your local GitLab Development Kit or GitLab Docker instance.
For a real-life example, refer to
[this failed job](https://gitlab.com/gitlab-org/gitlab/-/jobs/6418619509#L4970).
### Database import failures
If job is failing on setup stage prior to `gitlab:db:configure`
due to external dependencies, the job can be disabled by setting
`DISABLE_DB_MULTI_VERSION_UPGRADE=true` in GitLab project CI variables
to unblock the [broken master](https://handbook.gitlab.com/handbook/engineering/workflow/#broken-master).
Reach out to [Self-Managed Platform team](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/self-managed-platform-team/) to expedite debugging.

View File

@ -170,8 +170,6 @@ end
#### Estimated batch counters
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48233) in GitLab 13.7.
Estimated batch counter functionality handles `ActiveRecord::StatementInvalid` errors
when used through the provided `estimate_batch_distinct_count` method.
Errors return a value of `-1`.
@ -284,16 +282,12 @@ options:
### Event sourced aggregated metrics
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6.
To declare the aggregate of events collected with Internal Events, make sure `time_frame` does not include the `all` value, which is unavailable for Redis-sourced aggregated metrics.
While it is possible to aggregate EE-only events together with events that occur in all GitLab editions, it's important to remember that doing so may produce high variance between data collected from EE and CE GitLab instances.
### Database sourced aggregated metrics
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52784) in GitLab 13.9.
To declare an aggregate of metrics based on events collected from database, follow
these steps:

View File

@ -6,9 +6,6 @@ info: Any user with at least the Maintainer role can merge updates to this conte
# Service Ping development guidelines
> - Introduced in GitLab Ultimate 11.2, more statistics.
> - In GitLab 14.1, [renamed from Usage Ping to Service Ping](https://gitlab.com/groups/gitlab-org/-/epics/5990). In 14.0 and earlier, use the Usage Ping documentation for the Rails commands appropriate to your version.
Service Ping is a GitLab process that collects and sends a weekly payload to GitLab.
The payload provides important high-level data that helps our product, support,
and sales teams understand how GitLab is used. The data helps to:

View File

@ -90,89 +90,6 @@ However, it has the following limitations:
always runs as a process alongside other GitLab components on any given node. For Service Ping, none of the node data would therefore
appear to be associated to any of the services running, because they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics appears in Service Ping.
## Troubleshooting
### Cannot disable Service Ping with the configuration file
The method to disable Service Ping with the GitLab configuration file does not work in
GitLab versions 9.3.0 to 13.12.3. To disable it, you must use the Admin Area in
the GitLab UI instead. For more information, see
[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/333269).
GitLab functionality and application settings cannot override or circumvent
restrictions at the network layer. If Service Ping is blocked by your firewall,
you are not impacted by this bug.
#### Check if you are affected
You can check if you were affected by this bug by using the Admin Area or by
checking the configuration file of your GitLab instance:
- Using the Admin Area:
1. On the left sidebar, at the bottom, select **Admin Area**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand **Usage statistics**.
1. Are you able to check or uncheck the checkbox to disable Service Ping?
- If _yes_, your GitLab instance is not affected by this bug.
- If you can't check or uncheck the checkbox, you are affected by this bug.
See the steps on [how to fix this](#how-to-fix-the-cannot-disable-service-ping-bug).
- Checking your GitLab instance configuration file:
To check whether you're impacted by this bug, check your instance configuration
settings. The configuration file in which Service Ping can be disabled depends
on your installation and deployment method, but is typically one of the following:
- `/etc/gitlab/gitlab.rb` for Linux package installations and Docker.
- `charts.yaml` for GitLab Helm and cloud-native Kubernetes deployments.
- `gitlab.yml` for self-compiled installations.
To check the relevant configuration file for strings that indicate whether
Service Ping is disabled, you can use `grep`:
```shell
# Linux package
grep "usage_ping_enabled'\] = false" /etc/gitlab/gitlab.rb
# Kubernetes charts
grep "enableUsagePing: false" values.yaml
# From source
grep "usage_ping_enabled'\] = false" gitlab/config.yml
```
If you see any output after running the relevant command, your GitLab instance
may be affected by the bug. Otherwise, your instance is not affected.
#### How to fix the "Cannot disable Service Ping" bug
To work around this bug, you have two options:
- [Update](../../../update/index.md) to GitLab 13.12.4 or newer to fix this bug.
- If you can't update to GitLab 13.12.4 or newer, enable Service Ping in the
configuration file, then disable Service Ping in the UI. For example, if you're
using the Linux package:
1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_rails['usage_ping_enabled'] = true
```
1. Reconfigure GitLab:
```shell
sudo gitlab-ctl reconfigure
```
1. On the left sidebar, at the bottom, select **Admin Area**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand **Usage statistics**.
1. Clear the **Enable Service Ping** checkbox.
1. Select **Save Changes**.
## Generate Service Ping
### Generate or get the cached Service Ping in rails console

View File

@ -7,17 +7,15 @@ description: "Use Git LFS to manage binary assets, like images and video, withou
# Git Large File Storage (LFS)
Managing large files such as audio, video and graphics files has always been one
of the shortcomings of Git. The general recommendation is to not have Git repositories
larger than 1 GB to preserve performance.
Git Large File Storage (LFS) can manage large binary files efficiently in Git repositories.
It addresses challenges, such as repository performance and capacity limits.
For best performance, keep your repositories as small as possible.
Git LFS creates pointers to the actual file, stored elsewhere.
Your Git LFS client communicates with the GitLab server over HTTPS. It uses HTTP Basic authentication
to authorize client requests. After the request is authorized, Git LFS client receives
instructions on where to fetch or where to push the large file.
For GitLab.com repository size limits, see [account and limit settings](../../../administration/settings/account_and_limit_settings.md).
In the repository view, files tracked by Git LFS display an **LFS** badge next to the filename:
![Git LFS tracking status](img/lfs_badge_v16_0.png)
Git LFS clients communicate with server over HTTPS, with HTTP Basic authentication.
After the request is authorized, Git LFS client gets instructions on where to fetch or where to push the large file.
## Configure your GitLab server for Git LFS
@ -47,13 +45,19 @@ To do this:
Install the [Git LFS client](https://github.com/git-lfs/git-lfs) appropriate for
your operating system. GitLab requires version 1.0.1 or later of the Git LFS client.
After Git LFS is installed on the server and client, you can see the **LFS** badge
next to the filename:
![Git LFS tracking status](img/lfs_badge_v16_0.png)
## Known limitations
- Git LFS v1 original API is not supported, because it was deprecated early in LFS
development.
- When SSH is set as a remote, Git LFS objects still go through HTTPS.
- Any Git LFS request asks for HTTPS credentials, so you should use a good Git
credentials store.
- Even when Git communicates with the repository over SSH, Git LFS objects still
go through HTTPS.
- Because Git LFS requests require HTTPS credentials, you should use a good Git
[credentials store](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage).
- Git LFS always assumes HTTPS so if you have GitLab server on HTTP you must
[add the URL to Git configuration manually](troubleshooting.md#getsockopt-connection-refused).
- [Group wikis](../../../user/project/wiki/group.md) do not support Git LFS.
@ -65,16 +69,16 @@ When you add an LFS object to a repository, GitLab:
1. Creates an LFS object.
1. Associates the LFS object with the repository.
1. Queues a job to recalculate your project's statistics, including storage size and
LFS object storage. Your LFS object storage is the sum of the size of all LFS objects
associated with the repository.
LFS object storage. Your LFS object storage is the sum of the size of all LFS
objects associated with the repository.
When your repository is forked, LFS objects from the upstream project are associated
with the fork. When the fork is created, the LFS object storage for the fork is equal
to the storage used by the upstream project. If new LFS objects are added to the fork,
the total object storage changes for the fork, but not the upstream project.
When your repository is forked, the fork includes LFS objects from the upstream project.
The LFS object storage for the fork, at first, is the same size as the storage used by the upstream
project.
If new LFS objects are added to the fork, the total object storage increases only for the fork.
If you create a merge request from the fork back to the upstream project,
any new LFS objects in the fork become associated with the upstream project.
new LFS objects get associated with the upstream project.
## Using Git LFS
@ -89,27 +93,23 @@ git lfs install # initialize the Git LFS project
git lfs track "*.iso" # select the file extensions that you want to treat as large files
```
After you mark a file extension for tracking as a LFS object you can use
Git as usual without redoing the command to track a file with the same extension:
These commands create a `.gitattributes` file with the file types that you want to track.
In this case, Git LFS is now tracking `*.iso` files.
You can now use these commands to push a large `*.iso` file (and the new `.gitattributes` file) to
your repository:
```shell
cp ~/tmp/debian.iso ./ # copy a large file into the current directory
git add . # add the large file to the project
git commit -am "Added Debian iso" # commit the file meta data
git commit -am "Add Debian iso and .gitattributes" # commit the file meta data
git push origin main # sync the git repo and large file to the GitLab server
```
**Make sure** that `.gitattributes` is tracked by Git. Otherwise Git
LFS doesn't work properly for people cloning the project:
```shell
git add .gitattributes
git commit -am "Added .gitattributes to capture LFS tracking"
git push origin main
```
**Make sure** you've committed `.gitattributes` to your repository. Otherwise Git
LFS doesn't work properly for those who clone it:
Cloning the repository works the same as before. Git automatically detects the
LFS-tracked files and clones them via HTTP. If you performed the `git clone`
LFS-tracked files and clones them over HTTP. If you performed the `git clone`
command with a SSH URL, you have to enter your GitLab credentials for HTTP
authentication.
@ -117,8 +117,8 @@ authentication.
git clone git@gitlab.example.com:group/my-sample-project.git
```
If you already cloned the repository and you want to get the latest LFS object
that are on the remote repository, such as for a branch from origin:
If you already cloned the repository and want the latest LFS objects
that are on the remote repository:
```shell
git lfs fetch origin main
@ -138,10 +138,6 @@ To remove objects from LFS:
1. Use [`git filter-repo`](../../../user/project/repository/reducing_the_repo_size_using_git.md) to remove the objects from the repository.
1. Delete the relevant LFS lines for the objects you have removed from your `.gitattributes` file and commit those changes.
## File Locking
See the documentation on [File Locking](../../../user/project/file_lock.md).
## LFS objects in project archives
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) support for including Git LFS blobs inside [project source downloads](../../../user/project/repository/index.md) in GitLab 13.5 [with a flag](../../../administration/feature_flags.md) named `include_lfs_blobs_in_archive`. Disabled by default.
@ -165,6 +161,7 @@ Technical details about how this works can be found in the [development document
## Related topics
- Use Git LFS to set up [exclusive file locks](../../../user/project/file_lock.md#exclusive-file-locks).
- Blog post: [Getting started with Git LFS](https://about.gitlab.com/blog/2017/01/30/getting-started-with-git-lfs-tutorial/)
- [Git LFS developer information](../../../development/lfs.md)
- [GitLab Git Large File Storage (LFS) Administration](../../../administration/lfs/index.md) for self-managed instances

View File

@ -15,16 +15,21 @@ DETAILS:
> - Continuous Container Scanning [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435435) in GitLab 16.8 [with a flag](../../../administration/feature_flags.md) named `container_scanning_continuous_vulnerability_scans`. Disabled by default.
> - Continuous Container Scanning [enabled on GitLab.com, self-managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/437162) in GitLab 16.10.
Continuous Vulnerability Scanning detects new vulnerabilities outside a pipeline.
Your projects are automatically scanned whenever advisories are added to the [`GitLab Advisory Database`](https://advisories.gitlab.com/), or [`Trivy DB`](https://github.com/aquasecurity/trivy-db).
Projects that depend on the affected components have new vulnerabilities automatically created.
When advisories are added to either the [GitLab Advisory Database](https://advisories.gitlab.com/) or the
[Trivy Database](https://github.com/aquasecurity/trivy-db), Continuous Vulnerability Scanning
triggers a scan on all projects where either Container Scanning, Dependency Scanning, or both, are
enabled. If a new advisory affects an application or operating system dependency, it creates a
vulnerability in the project.
Continuous Vulnerability Scanning detects vulnerabilities in the latest CycloneDX SBOM reports for the default branch.
[Dependency Scanning](../dependency_scanning/index.md) and [Container Scanning](../container_scanning/index.md) are used to generate these reports.
NOTE:
If a new operating system package is added to either the GitLab Advisory Database or Trivy
Database, and an advisory for it already exists, a vulnerability is **not** created. Support for
improvements is proposed in [epic 11219](https://gitlab.com/groups/gitlab-org/-/epics/11219) and
[epic 8026](https://gitlab.com/groups/gitlab-org/-/epics/8026).
## Supported package types
Components with the following [package URL types](https://github.com/package-url/purl-spec/blob/346589846130317464b677bc4eab30bf5040183a/PURL-TYPES.rst) are supported:
Continuous Vulnerability Scanning supports components with the following [PURL types](https://github.com/package-url/purl-spec/blob/346589846130317464b677bc4eab30bf5040183a/PURL-TYPES.rst):
- `composer`
- `conan`

View File

@ -78,6 +78,9 @@ You can ask about a specific GitLab issue. For example:
- When you are viewing an issue in GitLab, you can ask `Generate a concise summary of the current issue.`
- `How can I improve the description of <link to your issue> so that readers understand the value and problems to be solved?`
NOTE:
If the issue contains a large amount of text (more than 40,000 words), GitLab Duo Chat might not be able to consider every word. The AI model has a limit to the amount of input it can process at one time.
### Ask about a specific epic
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128487) for SaaS in GitLab 16.3.
@ -89,6 +92,9 @@ You can ask about a specific GitLab epic. For example:
- When you are viewing an epic in GitLab, you can ask `Generate a concise summary of the opened epic.`
- `What are the unique use cases raised by commenters in <link to your epic>?`
NOTE:
If the epic contains a large amount of text (more than 40,000 words), GitLab Duo Chat might not be able to consider every word. The AI model has a limit to the amount of input it can process at one time.
### Ask about code
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122235) for SaaS in GitLab 16.1.

View File

@ -24,21 +24,16 @@ provided that the agent is properly configured for remote development.
## Remote development settings
To enable Remote Development and register a new workspace, the following GitLab Agent settings are mandatory:
- [`enabled`]
- [`dns_zone`]
| Setting | Description |
|-------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------|
| [`enabled`](#enabled) | Indicates whether remote development is enabled for the GitLab agent. |
| [`dns_zone`](#dns_zone) | DNS zone where workspaces are available. |
| [`gitlab_workspaces_proxy`](#gitlab_workspaces_proxy) | Namespace where [`gitlab-workspaces-proxy`](https://gitlab.com/gitlab-org/remote-development/gitlab-workspaces-proxy) is installed. |
| [`network_policy`](#network_policy) | Firewall rules for workspaces. |
| [`default_resources_per_workspace_container`](#default_resources_per_workspace_container) | Default requests and limits for CPU and memory per workspace container. |
| [`max_resources_per_workspace`](#max_resources_per_workspace) | Maximum requests and limits for CPU and memory per workspace. |
| [`workspaces_quota`](#workspaces_quota) | Maximum number of workspaces for the GitLab agent. |
| [`workspaces_per_user_quota`](#workspaces_per_user_quota) | Maximum number of workspaces per user. |
| Setting | Required | Description |
|-------------------------------------------------------------------------------------------|----------|-------------|
| [`enabled`](#enabled) | Yes | Indicates whether remote development is enabled for the GitLab agent. |
| [`dns_zone`](#dns_zone) | Yes | DNS zone where workspaces are available. |
| [`gitlab_workspaces_proxy`](#gitlab_workspaces_proxy) | No | Namespace where [`gitlab-workspaces-proxy`](https://gitlab.com/gitlab-org/remote-development/gitlab-workspaces-proxy) is installed. |
| [`network_policy`](#network_policy) | No | Firewall rules for workspaces. |
| [`default_resources_per_workspace_container`](#default_resources_per_workspace_container) | No | Default requests and limits for CPU and memory per workspace container. |
| [`max_resources_per_workspace`](#max_resources_per_workspace) | No | Maximum requests and limits for CPU and memory per workspace. |
| [`workspaces_quota`](#workspaces_quota) | No | Maximum number of workspaces for the GitLab agent. |
| [`workspaces_per_user_quota`](#workspaces_per_user_quota) | No | Maximum number of workspaces per user. |
NOTE:
If a setting has an invalid value, it's not possible to update any setting until you fix that value.

View File

@ -3,19 +3,19 @@
canonical: "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n"
static: "<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre
data-sourcepos=\"1:2-1:13\" class=\"code highlight js-syntax-highlight language-plaintext\"
lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">foo\tbaz\t\tbim</span></code></pre>\n<copy-code></copy-code>\n</div>"
v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">foo\tbaz\t\tbim</span></code></pre>\n<copy-code></copy-code>\n</div>"
wysiwyg: "<pre dir=\"auto\" class=\"content-editor-code-block undefined code highlight\"><code>foo\tbaz\t\tbim</code></pre>"
02_01_00__preliminaries__tabs__002:
canonical: "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n"
static: "<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre
data-sourcepos=\"1:4-1:15\" class=\"code highlight js-syntax-highlight language-plaintext\"
lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">foo\tbaz\t\tbim</span></code></pre>\n<copy-code></copy-code>\n</div>"
v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">foo\tbaz\t\tbim</span></code></pre>\n<copy-code></copy-code>\n</div>"
wysiwyg: "<pre dir=\"auto\" class=\"content-editor-code-block undefined code highlight\"><code>foo\tbaz\t\tbim</code></pre>"
02_01_00__preliminaries__tabs__003:
canonical: "<pre><code>a\ta\nὐ\ta\n</code></pre>\n"
static: "<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre
data-sourcepos=\"1:5-2:9\" class=\"code highlight js-syntax-highlight language-plaintext\"
lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">a\ta</span>\n<span
v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">a\ta</span>\n<span
id=\"LC2\" class=\"line\" lang=\"plaintext\">ὐ\ta</span></code></pre>\n<copy-code></copy-code>\n</div>"
wysiwyg: "<pre dir=\"auto\" class=\"content-editor-code-block undefined code highlight\"><code>a\ta\nὐ\ta</code></pre>"
02_01_00__preliminaries__tabs__004:
@ -49,7 +49,7 @@
<li data-sourcepos="1:1-3:5">
<p data-sourcepos="1:3-1:5">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:2-3:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> bar</span></code></pre>
<pre data-sourcepos="3:2-3:5" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> bar</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -65,7 +65,7 @@
static: |-
<blockquote data-sourcepos="1:1-1:6" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-1:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span></code></pre>
<pre data-sourcepos="1:3-1:6" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
@ -83,7 +83,7 @@
<ul data-sourcepos="1:1-1:6" dir="auto">
<li data-sourcepos="1:1-1:6">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-1:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span></code></pre>
<pre data-sourcepos="1:3-1:6" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -97,7 +97,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:4" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
<pre data-sourcepos="1:5-2:4" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
<span id="LC2" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
@ -218,7 +218,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***</span></code></pre>
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -461,7 +461,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo</span></code></pre>
<pre data-sourcepos="1:5-1:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -658,7 +658,7 @@
<hr />
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-4:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
<pre data-sourcepos="1:5-4:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
<span id="LC2" class="line" lang="plaintext">---</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">Foo</span></code></pre>
@ -803,7 +803,7 @@
<p>Baz</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="yaml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-yaml" lang="yaml" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="s">Foo</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="yaml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-yaml" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="s">Foo</span></span></code></pre>
<copy-code></copy-code>
</div>
<h2 data-sourcepos="4:1-6:3" dir="auto">
@ -826,7 +826,7 @@
<hr />
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-2:3" data-canonical-lang="yaml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-yaml" lang="yaml" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:1-2:3" data-canonical-lang="yaml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-yaml" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -852,7 +852,7 @@
<hr />
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<hr data-sourcepos="2:1-2:3">
@ -950,7 +950,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:25" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a simple</span>
<pre data-sourcepos="1:5-2:25" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a simple</span>
<span id="LC2" class="line" lang="plaintext"> indented code block</span></code></pre>
<copy-code></copy-code>
</div>
@ -1004,7 +1004,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-4:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a/&gt;</span>
<pre data-sourcepos="1:5-4:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a/&gt;</span>
<span id="LC2" class="line" lang="plaintext">*hi*</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">- one</span></code></pre>
@ -1027,7 +1027,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-7:10" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">chunk1</span>
<pre data-sourcepos="1:5-7:10" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">chunk1</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext">chunk2</span>
<span id="LC4" class="line" lang="plaintext"></span>
@ -1048,7 +1048,7 @@
canonical: "<pre><code>chunk1\n \n chunk2\n</code></pre>\n"
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-3:12" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">chunk1</span>
<pre data-sourcepos="1:5-3:12" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">chunk1</span>
<span id="LC2" class="line" lang="plaintext"> </span>
<span id="LC3" class="line" lang="plaintext"> chunk2</span></code></pre>
<copy-code></copy-code>
@ -1072,7 +1072,7 @@
<p>bar</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="2:1-2:3" dir="auto">bar</p>
@ -1092,13 +1092,13 @@
<h1 data-sourcepos="1:1-1:9" dir="auto">
<a id="user-content-heading" class="anchor" href="#heading" aria-hidden="true"></a>Heading</h1>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="2:5-2:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="2:5-2:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<h2 data-sourcepos="3:1-5:7" dir="auto">
<a id="user-content-heading-1" class="anchor" href="#heading-1" aria-hidden="true"></a>Heading</h2>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:5-5:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="5:5-5:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<hr data-sourcepos="6:1-6:4">
@ -1115,7 +1115,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
<pre data-sourcepos="1:5-2:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
<span id="LC2" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
@ -1128,7 +1128,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:5-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="3:5-5:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1137,7 +1137,7 @@
canonical: "<pre><code>foo \n</code></pre>\n"
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span></code></pre>
<pre data-sourcepos="1:5-1:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1149,7 +1149,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;</span>
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;</span>
<span id="LC2" class="line" lang="plaintext"> &gt;</span></code></pre>
<copy-code></copy-code>
</div>
@ -1163,7 +1163,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;</span>
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;</span>
<span id="LC2" class="line" lang="plaintext"> &gt;</span></code></pre>
<copy-code></copy-code>
</div>
@ -1184,7 +1184,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">~~~</span></code></pre>
<copy-code></copy-code>
</div>
@ -1198,7 +1198,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">```</span></code></pre>
<copy-code></copy-code>
</div>
@ -1212,7 +1212,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-4:6" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">```</span></code></pre>
<copy-code></copy-code>
</div>
@ -1226,7 +1226,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:4" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-4:4" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">~~~</span></code></pre>
<copy-code></copy-code>
</div>
@ -1238,7 +1238,7 @@
<pre><code></code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-1:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:1-1:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1251,7 +1251,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<span id="LC2" class="line" lang="plaintext">```</span>
<span id="LC3" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
@ -1270,7 +1270,7 @@
static: |-
<blockquote data-sourcepos="1:1-2:5" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-3:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<pre data-sourcepos="1:3-3:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
@ -1282,7 +1282,7 @@
canonical: "<pre><code>\n \n</code></pre>\n"
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<span id="LC2" class="line" lang="plaintext"> </span></code></pre>
<copy-code></copy-code>
</div>
@ -1293,7 +1293,7 @@
<pre><code></code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-2:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:1-2:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1305,7 +1305,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:2-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:2-4:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
@ -1320,7 +1320,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-5:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:3-5:5" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">aaa</span>
<span id="LC3" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
@ -1337,7 +1337,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:4-5:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:4-5:6" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext"> aaa</span>
<span id="LC3" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
@ -1354,7 +1354,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-3:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
<pre data-sourcepos="1:5-3:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
<span id="LC2" class="line" lang="plaintext">aaa</span>
<span id="LC3" class="line" lang="plaintext">```</span></code></pre>
<copy-code></copy-code>
@ -1369,7 +1369,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<pre data-sourcepos="1:1-3:5" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1380,7 +1380,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:4-3:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<pre data-sourcepos="1:4-3:5" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1392,7 +1392,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-3:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext"> ```</span></code></pre>
<copy-code></copy-code>
</div>
@ -1416,7 +1416,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-3:6" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">~~~ ~~</span></code></pre>
<copy-code></copy-code>
</div>
@ -1432,7 +1432,7 @@
static: |-
<p data-sourcepos="1:1-1:3" dir="auto">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="2:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="2:1-4:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="5:1-5:3" dir="auto">baz</p>
@ -1450,7 +1450,7 @@
<h2 data-sourcepos="1:1-3:3" dir="auto">
<a id="user-content-foo" class="anchor" href="#foo" aria-hidden="true"></a>foo</h2>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:1-5:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="3:1-5:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
<h1 data-sourcepos="6:1-6:5" dir="auto">
@ -1467,7 +1467,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:3" data-canonical-lang="ruby" class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></span>
<pre data-sourcepos="1:1-5:3" data-canonical-lang="ruby" class="code highlight js-syntax-highlight language-ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></span>
<span id="LC2" class="line" lang="ruby"> <span class="k">return</span> <span class="mi">3</span></span>
<span id="LC3" class="line" lang="ruby"><span class="k">end</span></span></code></pre>
<copy-code></copy-code>
@ -1484,7 +1484,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:7" data-canonical-lang="ruby" data-lang-params="startline=3 $%@#$" class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></span>
<pre data-sourcepos="1:1-5:7" data-canonical-lang="ruby" data-lang-params="startline=3 $%@#$" class="code highlight js-syntax-highlight language-ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></span>
<span id="LC2" class="line" lang="ruby"> <span class="k">return</span> <span class="mi">3</span></span>
<span id="LC3" class="line" lang="ruby"><span class="k">end</span></span></code></pre>
<copy-code></copy-code>
@ -1498,7 +1498,7 @@
<pre><code class="language-;"></code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-2:4" data-canonical-lang=";" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:1-2:4" data-canonical-lang=";" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1519,7 +1519,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="aa" data-lang-params="``` ~~~" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="aa" data-lang-params="``` ~~~" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1530,7 +1530,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``` aaa</span></code></pre>
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``` aaa</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1796,7 +1796,7 @@
<p>okay</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<pre class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<span id="LC2" class="line" lang="plaintext">import Text.HTML.TagSoup</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">main :: IO ()</span>
@ -1987,7 +1987,7 @@
</code></pre>
static: " \n<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre
data-sourcepos=\"3:5-3:16\" class=\"code highlight js-syntax-highlight language-plaintext\"
lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">&lt;!--
v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">&lt;!--
foo --&gt;</span></code></pre>\n<copy-code></copy-code>\n</div>"
wysiwyg: |-
<pre dir="auto" class="content-editor-code-block undefined code highlight"><code>&lt;!-- foo --&gt;</code></pre>
@ -1999,7 +1999,7 @@
static: |2-
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:5-3:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;</span></code></pre>
<pre data-sourcepos="3:5-3:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;</span></code></pre>
<copy-code></copy-code>
</div>
</div>
@ -2110,7 +2110,7 @@
<table dir="auto">
<tr>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:5-8:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;td&gt;</span>
<pre data-sourcepos="5:5-8:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;td&gt;</span>
<span id="LC2" class="line" lang="plaintext"> Hi</span>
<span id="LC3" class="line" lang="plaintext">&lt;/td&gt;</span></code></pre>
<copy-code></copy-code>
@ -2303,7 +2303,7 @@
<p>[foo]</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url "title"</span></code></pre>
<pre data-sourcepos="1:5-2:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url "title"</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="3:1-3:5" dir="auto">[foo]</p>
@ -2317,7 +2317,7 @@
<p>[foo]</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span></code></pre>
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="5:1-5:5" dir="auto">[foo]</p>
@ -2486,7 +2486,7 @@
<p>bbb</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="2:1-2:3" dir="auto">bbb</p>
@ -2833,7 +2833,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-3:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; # Foo</span>
<pre data-sourcepos="1:5-3:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; # Foo</span>
<span id="LC2" class="line" lang="plaintext">&gt; bar</span>
<span id="LC3" class="line" lang="plaintext">&gt; baz</span></code></pre>
<copy-code></copy-code>
@ -2923,12 +2923,12 @@
static: |-
<blockquote data-sourcepos="1:1-1:9" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:7-1:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:7-1:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="2:5-2:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="2:5-2:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -2944,13 +2944,13 @@
static: |-
<blockquote data-sourcepos="1:1-1:5" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-2:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:3-2:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
<p data-sourcepos="2:1-2:3" dir="auto">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code></code></pre>
<pre data-sourcepos="3:1-3:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -3181,7 +3181,7 @@
static: |-
<blockquote data-sourcepos="1:1-1:10" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:7-1:10" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre>
<pre data-sourcepos="1:7-1:10" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
@ -3204,7 +3204,7 @@
<p data-sourcepos="1:1-2:15" dir="auto">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:5-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:5-5:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:1-6:16" dir="auto">
@ -3234,7 +3234,7 @@
<p data-sourcepos="1:5-2:19">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:9-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:9-5:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:5-6:20">
@ -3288,7 +3288,7 @@
<li data-sourcepos="1:2-2:0">one</li>
</ul>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:5-3:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> two</span></code></pre>
<pre data-sourcepos="3:5-3:8" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> two</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -3402,7 +3402,7 @@
<li data-sourcepos="1:1-9:9">
<p data-sourcepos="1:5-1:7">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:5-5:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="3:5-5:7" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="7:5-7:7">baz</p>
@ -3430,7 +3430,7 @@
<li data-sourcepos="1:1-6:9">
<p data-sourcepos="1:3-1:5">Foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:7-6:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span>
<pre data-sourcepos="3:7-6:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">baz</span></code></pre>
@ -3504,7 +3504,7 @@
<li data-sourcepos="1:1-3:9">
<p data-sourcepos="1:3-1:5">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:7-3:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="3:7-3:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3525,7 +3525,7 @@
<li data-sourcepos="1:3-3:14">
<p data-sourcepos="1:8-1:10">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:12-3:14" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="3:12-3:14" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3541,12 +3541,12 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="1:5-2:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="3:1-3:9" dir="auto">paragraph</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:5-5:13" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<pre data-sourcepos="5:5-5:13" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -3568,12 +3568,12 @@
<ol data-sourcepos="1:1-5:16" dir="auto">
<li data-sourcepos="1:1-5:16">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:8-2:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="1:8-2:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="3:4-3:12">paragraph</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:8-5:16" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<pre data-sourcepos="5:8-5:16" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3595,12 +3595,12 @@
<ol data-sourcepos="1:1-5:16" dir="auto">
<li data-sourcepos="1:1-5:16">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:8-2:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> indented code</span></code></pre>
<pre data-sourcepos="1:8-2:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> indented code</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="3:4-3:12">paragraph</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:8-5:16" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<pre data-sourcepos="5:8-5:16" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3666,13 +3666,13 @@
<li data-sourcepos="1:1-2:5">foo</li>
<li data-sourcepos="3:1-6:5">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:3-6:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="4:3-6:5" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
</li>
<li data-sourcepos="7:1-8:9">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="8:7-8:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">baz</span></code></pre>
<pre data-sourcepos="8:7-8:9" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">baz</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3800,7 +3800,7 @@
<p data-sourcepos="1:6-2:20">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:10-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:10-5:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:6-6:21">
@ -3830,7 +3830,7 @@
<p data-sourcepos="1:7-2:21">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:11-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:11-5:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:7-6:22">
@ -3860,7 +3860,7 @@
<p data-sourcepos="1:8-2:22">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:12-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:12-5:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:8-6:23">
@ -3882,7 +3882,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-6:24" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. A paragraph</span>
<pre data-sourcepos="1:5-6:24" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. A paragraph</span>
<span id="LC2" class="line" lang="plaintext"> with two lines.</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext"> indented code</span>
@ -3916,7 +3916,7 @@
<p data-sourcepos="1:7-2:15">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:11-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:11-5:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:7-6:22">
@ -4342,7 +4342,7 @@
</ul>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="9:5-9:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre>
<pre data-sourcepos="9:5-9:8" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4440,7 +4440,7 @@
</li>
</ol>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:5-5:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">3. c</span></code></pre>
<pre data-sourcepos="5:5-5:8" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">3. c</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4570,7 +4570,7 @@
<li data-sourcepos="1:1-1:3">a</li>
<li data-sourcepos="2:1-6:5">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="2:3-6:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">b</span>
<pre data-sourcepos="2:3-6:5" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">b</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"></span></code></pre>
<copy-code></copy-code>
@ -4647,7 +4647,7 @@
<p data-sourcepos="2:5-2:5">b</p>
</blockquote>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:3-5:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">c</span></code></pre>
<pre data-sourcepos="3:3-5:5" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">c</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -4698,7 +4698,7 @@
<ol data-sourcepos="1:1-5:6" dir="auto">
<li data-sourcepos="1:1-5:6">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:4-3:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:4-3:6" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="5:4-5:6">bar</p>
@ -4845,7 +4845,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[\]</span></code></pre>
<pre data-sourcepos="1:5-1:8" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[\]</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4856,7 +4856,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[\]</span></code></pre>
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[\]</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4896,7 +4896,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="foo+bar" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="foo+bar" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4986,7 +4986,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="föö" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="föö" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -5004,7 +5004,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:18" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">f&amp;ouml;f&amp;ouml;</span></code></pre>
<pre data-sourcepos="1:5-1:18" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">f&amp;ouml;f&amp;ouml;</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -7705,7 +7705,7 @@
</pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="yaml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-yaml" lang="yaml" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">YAML front matter</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="yaml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-yaml" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">YAML front matter</span></span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -7719,7 +7719,7 @@
</pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="toml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-toml" lang="toml" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="err">title:</span> <span class="err">TOML</span> <span class="err">front</span> <span class="err">matter</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="toml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-toml" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="err">title:</span> <span class="err">TOML</span> <span class="err">front</span> <span class="err">matter</span></span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -7735,7 +7735,7 @@
</pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:3" data-canonical-lang="json" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-json" lang="json" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
<pre data-sourcepos="1:1-5:3" data-canonical-lang="json" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-json" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
<span id="LC2" class="line" lang="json"><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"JSON front matter"</span></span>
<span id="LC3" class="line" lang="json"><span class="p">}</span></span></code></pre>
<copy-code></copy-code>
@ -8051,7 +8051,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="javascript" class="code highlight js-syntax-highlight language-javascript" lang="javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="javascript" class="code highlight js-syntax-highlight language-javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -8061,7 +8061,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> plaintext</span></code></pre>
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> plaintext</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -8071,7 +8071,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="foobar" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> custom_language = &gt;&gt; this &lt;&lt;</span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="foobar" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> custom_language = &gt;&gt; this &lt;&lt;</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -8131,7 +8131,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-11:3" data-canonical-lang="nomnoml" class="code highlight js-syntax-highlight language-nomnoml" lang="nomnoml" v-pre="true"><code><span id="LC1" class="line" lang="nomnoml"> #stroke: #a86128</span>
<pre data-sourcepos="1:1-11:3" data-canonical-lang="nomnoml" class="code highlight js-syntax-highlight language-nomnoml" v-pre="true"><code><span id="LC1" class="line" lang="nomnoml"> #stroke: #a86128</span>
<span id="LC2" class="line" lang="nomnoml"> [&lt;frame&gt;Decorator pattern|</span>
<span id="LC3" class="line" lang="nomnoml"> [&lt;abstract&gt;Component||+ operation()]</span>
<span id="LC4" class="line" lang="nomnoml"> [Client] depends --&gt; [Component]</span>
@ -8157,7 +8157,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-7:3" data-canonical-lang="plantuml" class="code highlight js-syntax-highlight language-plantuml" lang="plantuml" v-pre="true"><code><span id="LC1" class="line" lang="plantuml"> Alice -&gt; Bob: Authentication Request</span>
<pre data-sourcepos="1:1-7:3" data-canonical-lang="plantuml" class="code highlight js-syntax-highlight language-plantuml" v-pre="true"><code><span id="LC1" class="line" lang="plantuml"> Alice -&gt; Bob: Authentication Request</span>
<span id="LC2" class="line" lang="plantuml"> Bob --&gt; Alice: Authentication Response</span>
<span id="LC3" class="line" lang="plantuml"></span>
<span id="LC4" class="line" lang="plantuml"> Alice -&gt; Bob: Another authentication Request</span>
@ -8175,7 +8175,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="plantuml" class="code highlight js-syntax-highlight language-plantuml" lang="plantuml" v-pre="true"><code><span id="LC1" class="line" lang="plantuml">A -&gt; B : Text with norwegian characters: æøå</span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="plantuml" class="code highlight js-syntax-highlight language-plantuml" v-pre="true"><code><span id="LC1" class="line" lang="plantuml">A -&gt; B : Text with norwegian characters: æøå</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -8249,7 +8249,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:3" data-canonical-lang="json" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-json" lang="json" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
<pre data-sourcepos="1:1-5:3" data-canonical-lang="json" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-json" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
<span id="LC2" class="line" lang="json"><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Page title"</span></span>
<span id="LC3" class="line" lang="json"><span class="p">}</span></span></code></pre>
<copy-code></copy-code>
@ -8263,7 +8263,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="toml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-toml" lang="toml" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="py">title</span> <span class="p">=</span> <span class="s">"Page title"</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="toml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-toml" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="py">title</span> <span class="p">=</span> <span class="s">"Page title"</span></span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -8273,7 +8273,7 @@
TODO: Write canonical HTML for this example
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="yaml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-yaml" lang="yaml" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">Page title</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" data-canonical-lang="yaml" data-lang-params="frontmatter" class="code highlight js-syntax-highlight language-yaml" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">Page title</span></span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -8411,7 +8411,7 @@
<p data-sourcepos="1:1-1:36" dir="auto">This math is inline <code data-sourcepos="1:23-1:33" data-math-style="inline" class="code math js-render-math">a^2+b^2=c^2</code>.</p>
<p data-sourcepos="3:1-3:27" dir="auto">This is on a separate line:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:1-7:3" data-canonical-lang="math" data-math-style="display" class="js-render-math code highlight js-syntax-highlight language-math" lang="math" v-pre="true"><code><span id="LC1" class="line" lang="math">a^2+b^2=c^2</span></code></pre>
<pre data-sourcepos="5:1-7:3" data-canonical-lang="math" data-math-style="display" class="js-render-math code highlight js-syntax-highlight language-math" v-pre="true"><code><span id="LC1" class="line" lang="math">a^2+b^2=c^2</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -8696,7 +8696,7 @@
<p data-sourcepos="20:7-20:39">Blockquotes can be in a footnote.</p>
</blockquote>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="22:9-23:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">as well as code blocks</span></code></pre>
<pre data-sourcepos="22:9-23:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">as well as code blocks</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="24:5-24:37">or, naturally, simple paragraphs. <a href="#fnref-footnote-42" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
@ -8706,7 +8706,7 @@
</li>
<li data-sourcepos="12:1-14:0" id="fn-codeblock-note-42">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="13:9-14:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">this is now a code block (8 spaces indentation)</span></code></pre>
<pre data-sourcepos="13:9-14:0" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">this is now a code block (8 spaces indentation)</span></code></pre>
<copy-code></copy-code>
</div>
<a href="#fnref-codeblock-note-42" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a>

File diff suppressed because it is too large Load Diff

View File

@ -289,11 +289,11 @@ GitLab Flavored Markdown specification.</p>
<div>
<div><a href="#example-674">Example 674</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="55:1-57:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [ ] incomplete</span></code></pre>
<pre data-sourcepos="55:1-57:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [ ] incomplete</span></code></pre>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="59:1-67:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;ul&gt;</span>
<pre data-sourcepos="59:1-67:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;ul&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;li&gt;</span>
<span id="LC3" class="line" lang="plaintext">&lt;task-button/&gt;</span>
<span id="LC4" class="line" lang="plaintext">&lt;input type="checkbox" disabled/&gt;</span>
@ -307,11 +307,11 @@ GitLab Flavored Markdown specification.</p>
<div>
<div><a href="#example-675">Example 675</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="75:1-77:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [x] completed</span></code></pre>
<pre data-sourcepos="75:1-77:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [x] completed</span></code></pre>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="79:1-87:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;ul&gt;</span>
<pre data-sourcepos="79:1-87:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;ul&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;li&gt;</span>
<span id="LC3" class="line" lang="plaintext">&lt;task-button/&gt;</span>
<span id="LC4" class="line" lang="plaintext">&lt;input type="checkbox" checked disabled/&gt;</span>
@ -325,11 +325,11 @@ GitLab Flavored Markdown specification.</p>
<div>
<div><a href="#example-676">Example 676</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="95:1-97:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span></code></pre>
<pre data-sourcepos="95:1-97:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span></code></pre>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="99:1-109:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;ul&gt;</span>
<pre data-sourcepos="99:1-109:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;ul&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;li&gt;</span>
<span id="LC3" class="line" lang="plaintext">&lt;task-button/&gt;</span>
<span id="LC4" class="line" lang="plaintext">&lt;input type="checkbox" data-inapplicable disabled&gt;</span>
@ -346,13 +346,13 @@ loose text; it has strikethrough applied with CSS.</p>
<div>
<div><a href="#example-677">Example 677</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="118:1-122:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
<pre data-sourcepos="118:1-122:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"> text in loose list</span></code></pre>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="124:1-139:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;ul&gt;</span>
<pre data-sourcepos="124:1-139:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;ul&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;li&gt;</span>
<span id="LC3" class="line" lang="plaintext">&lt;p&gt;</span>
<span id="LC4" class="line" lang="plaintext">&lt;task-button/&gt;</span>
@ -379,13 +379,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
<div>
<div><a href="#example-678">Example 678</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="155:1-159:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">---</span>
<pre data-sourcepos="155:1-159:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">---</span>
<span id="LC2" class="line" lang="plaintext">title: YAML front matter</span>
<span id="LC3" class="line" lang="plaintext">---</span></code></pre>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="161:1-167:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;pre&gt;</span>
<pre data-sourcepos="161:1-167:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;pre&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;code&gt;</span>
<span id="LC3" class="line" lang="plaintext">title: YAML front matter</span>
<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;</span>
@ -397,13 +397,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
<div>
<div><a href="#example-679">Example 679</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="175:1-179:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">+++</span>
<pre data-sourcepos="175:1-179:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">+++</span>
<span id="LC2" class="line" lang="plaintext">title: TOML front matter</span>
<span id="LC3" class="line" lang="plaintext">+++</span></code></pre>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="181:1-187:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;pre&gt;</span>
<pre data-sourcepos="181:1-187:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;pre&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;code&gt;</span>
<span id="LC3" class="line" lang="plaintext">title: TOML front matter</span>
<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;</span>
@ -415,7 +415,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
<div>
<div><a href="#example-680">Example 680</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="195:1-201:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">;;;</span>
<pre data-sourcepos="195:1-201:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">;;;</span>
<span id="LC2" class="line" lang="plaintext">{</span>
<span id="LC3" class="line" lang="plaintext"> "title": "JSON front matter"</span>
<span id="LC4" class="line" lang="plaintext">}</span>
@ -423,7 +423,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="203:1-211:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;pre&gt;</span>
<pre data-sourcepos="203:1-211:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;pre&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;code&gt;</span>
<span id="LC3" class="line" lang="plaintext">{</span>
<span id="LC4" class="line" lang="plaintext"> "title": "JSON front matter"</span>
@ -437,7 +437,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
<div>
<div><a href="#example-681">Example 681</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="219:1-225:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">text</span>
<pre data-sourcepos="219:1-225:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">text</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext">---</span>
<span id="LC4" class="line" lang="plaintext">title: YAML front matter</span>
@ -445,7 +445,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="227:1-231:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;p&gt;text&lt;/p&gt;</span>
<pre data-sourcepos="227:1-231:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;p&gt;text&lt;/p&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;hr&gt;</span>
<span id="LC3" class="line" lang="plaintext">&lt;h2&gt;title: YAML front matter&lt;/h2&gt;</span></code></pre>
<copy-code></copy-code>
@ -455,13 +455,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
<div>
<div><a href="#example-682">Example 682</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="239:1-243:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ---</span>
<pre data-sourcepos="239:1-243:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ---</span>
<span id="LC2" class="line" lang="plaintext">title: YAML front matter</span>
<span id="LC3" class="line" lang="plaintext">---</span></code></pre>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="245:1-248:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;hr&gt;</span>
<pre data-sourcepos="245:1-248:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;hr&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;h2&gt;title: YAML front matter&lt;/h2&gt;</span></code></pre>
<copy-code></copy-code>
</div>
@ -481,7 +481,7 @@ Add either the <code data-sourcepos="264:17-264:25">[[_TOC_]]</code> tag or the
<div>
<div><a href="#example-683">Example 683</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="269:1-275:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[TOC]</span>
<pre data-sourcepos="269:1-275:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[TOC]</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
<span id="LC4" class="line" lang="plaintext"></span>
@ -489,7 +489,7 @@ Add either the <code data-sourcepos="264:17-264:25">[[_TOC_]]</code> tag or the
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="277:1-288:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;nav&gt;</span>
<pre data-sourcepos="277:1-288:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;nav&gt;</span>
<span id="LC2" class="line" lang="plaintext"> &lt;ul&gt;</span>
<span id="LC3" class="line" lang="plaintext"> &lt;li&gt;&lt;a href="#heading-1"&gt;Heading 1&lt;/a&gt;&lt;/li&gt;</span>
<span id="LC4" class="line" lang="plaintext"> &lt;ul&gt;</span>
@ -505,7 +505,7 @@ Add either the <code data-sourcepos="264:17-264:25">[[_TOC_]]</code> tag or the
<div>
<div><a href="#example-684">Example 684</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="294:1-300:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
<pre data-sourcepos="294:1-300:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
<span id="LC4" class="line" lang="plaintext"></span>
@ -513,7 +513,7 @@ Add either the <code data-sourcepos="264:17-264:25">[[_TOC_]]</code> tag or the
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="302:1-313:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;nav&gt;</span>
<pre data-sourcepos="302:1-313:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;nav&gt;</span>
<span id="LC2" class="line" lang="plaintext"> &lt;ul&gt;</span>
<span id="LC3" class="line" lang="plaintext"> &lt;li&gt;&lt;a href="#heading-1"&gt;Heading 1&lt;/a&gt;&lt;/li&gt;</span>
<span id="LC4" class="line" lang="plaintext"> &lt;ul&gt;</span>
@ -531,7 +531,7 @@ line.</p>
<div>
<div><a href="#example-685">Example 685</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="322:1-328:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
<pre data-sourcepos="322:1-328:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
<span id="LC2" class="line" lang="plaintext">text</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">text</span>
@ -539,7 +539,7 @@ line.</p>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="330:1-333:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;p&gt;[[&lt;em&gt;TOC&lt;/em&gt;]]text&lt;/p&gt;</span>
<pre data-sourcepos="330:1-333:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;p&gt;[[&lt;em&gt;TOC&lt;/em&gt;]]text&lt;/p&gt;</span>
<span id="LC2" class="line" lang="plaintext">&lt;p&gt;text[TOC]&lt;/p&gt;</span></code></pre>
<copy-code></copy-code>
</div>
@ -548,13 +548,13 @@ line.</p>
<div>
<div><a href="#example-686">Example 686</a></div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="341:1-345:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> [[_TOC_]]</span>
<pre data-sourcepos="341:1-345:32" data-canonical-lang="example" data-lang-params="gitlab" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> [[_TOC_]]</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"># Heading 1</span></code></pre>
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="347:1-354:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;nav&gt;</span>
<pre data-sourcepos="347:1-354:32" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;nav&gt;</span>
<span id="LC2" class="line" lang="plaintext"> &lt;ul&gt;</span>
<span id="LC3" class="line" lang="plaintext"> &lt;li&gt;&lt;a href="#heading-1"&gt;Heading 1&lt;/a&gt;&lt;/li&gt;</span>
<span id="LC4" class="line" lang="plaintext"> &lt;/ul&gt;</span>

View File

@ -71,7 +71,7 @@ module Banzai
end
doc.xpath(XPATH_LANG_TAG).each do |node|
node.attributes['lang'].value = node.attributes['lang'].value.gsub(SPAN_REGEX, '\1') if node.attributes['lang']
node.attributes['lang'].value = node.attributes['lang'].value.gsub(SPAN_REGEX, '\1') if node.attributes['lang']
end
end

View File

@ -66,7 +66,6 @@ module Banzai
pre_node.add_class(CSS_CLASSES)
pre_node.add_class("language-#{language}") if language
pre_node.set_attribute('lang', language)
pre_node.set_attribute('v-pre', 'true')
copy_code_btn = "<copy-code></copy-code>" unless language == 'suggestion'

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
module ClickHouse
module WriteBuffer
BUFFER_KEY = 'clickhouse_write_buffer'
class << self
def write_event(event_hash)
Gitlab::Redis::SharedState.with do |redis|
redis.lpush(BUFFER_KEY, event_hash.to_json)
end
end
end
end
end

View File

@ -31,6 +31,8 @@ module Gitlab
value: component.resource_type_before_type_cast
}
)
::Ci::Components::Usages::CreateService.new(component, used_by_project: project).execute
end
def included_catalog_components

View File

@ -6,6 +6,7 @@ module Gitlab
SUCCESS_STATUS = :success
FAILED_STATUS = :failed
INACTIVE_STATUS = :inactive
WARNING_STATUS = :warning
attr_reader :status, :payload
@ -25,6 +26,10 @@ module Gitlab
new(status: INACTIVE_STATUS, payload: default_payload.merge(**payload))
end
def self.warning(payload: {})
new(status: WARNING_STATUS, payload: default_payload.merge(**payload))
end
def self.from_hash(data)
new(
status: data.fetch(:status).to_sym,

View File

@ -3553,6 +3553,9 @@ msgstr ""
msgid "AdminSettings|Allow migrating GitLab groups and projects by direct transfer"
msgstr ""
msgid "AdminSettings|Allow runner registration token"
msgstr ""
msgid "AdminSettings|Auto DevOps domain"
msgstr ""
@ -3931,6 +3934,9 @@ msgstr ""
msgid "AdminSettings|Users and groups must accept the invitation before they're added to a group or project."
msgstr ""
msgid "AdminSettings|When disabled, runner registration tokens are disabled from runner pages, and maintainers and owners cannot use registration tokens to register runners. They can use runner authentication tokens instead as the more secure runner registration method."
msgstr ""
msgid "AdminSettings|When to delete inactive projects"
msgstr ""
@ -43527,6 +43533,9 @@ msgstr ""
msgid "Runners|Created by %{user} %{timeAgo}"
msgstr ""
msgid "Runners|Creating runners with runner registration tokens is disabled. %{linkStart}Learn more%{linkEnd}."
msgstr ""
msgid "Runners|Creator"
msgstr ""
@ -43652,9 +43661,6 @@ msgstr ""
msgid "Runners|Idle"
msgstr ""
msgid "Runners|If both settings are disabled, new runners cannot be registered."
msgstr ""
msgid "Runners|If you haven't already configured your Google Cloud project, this step enables the required services and creates a service account with the required permissions. "
msgstr ""
@ -43745,7 +43751,7 @@ msgstr ""
msgid "Runners|Median"
msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgid "Runners|Members of the %{type} can create runners"
msgstr ""
msgid "Runners|Minor version upgrades are available."
@ -52944,6 +52950,9 @@ msgstr ""
msgid "Timeout for the fastest Gitaly operations (in seconds)."
msgstr ""
msgid "Timeout: Element not found"
msgstr ""
msgid "Timezone"
msgstr ""

View File

@ -203,7 +203,7 @@ function install_gitlab_gem() {
}
function install_tff_gem() {
run_timed_command "gem install test_file_finder --no-document --version 0.3.0"
run_timed_command "gem install test_file_finder --no-document --version 0.3.1"
}
function install_activesupport_gem() {

View File

@ -11,8 +11,11 @@ RSpec.describe Groups::RunnersController, feature_category: :fleet_visibility do
let!(:project_runner) { create(:ci_runner, :project, projects: [project]) }
let!(:instance_runner) { create(:ci_runner, :instance) }
let(:runner_registration_enabled) { true }
before do
namespace_settings.update!(runner_registration_enabled: runner_registration_enabled)
sign_in(user)
end
@ -76,6 +79,17 @@ RSpec.describe Groups::RunnersController, feature_category: :fleet_visibility do
expect(assigns(:group_runner_registration_token)).not_to be_nil
expect(assigns(:group_new_runner_path)).to eq(new_group_runner_path(group))
end
context 'when runner registration is disabled' do
let(:runner_registration_enabled) { false }
it 'does not expose runner creation and registration variables' do
execute_get_request
expect(assigns(:group_runner_registration_token)).to be_nil
expect(assigns(:group_new_runner_path)).to be_nil
end
end
end
context 'when user is not maintainer' do

View File

@ -5,8 +5,11 @@ require('spec_helper')
RSpec.describe Projects::Settings::CiCdController, feature_category: :continuous_integration do
let_it_be(:user) { create(:user) }
let_it_be(:project_auto_devops) { create(:project_auto_devops) }
let_it_be(:project) { project_auto_devops.project }
let(:project) { project_auto_devops.project }
before_all do
project.namespace.namespace_settings = create(:namespace_settings, allow_runner_registration_token: true)
end
context 'as a maintainer' do
before do

View File

@ -608,4 +608,14 @@ FactoryBot.define do
path { 'gitlab-profile' }
files { { 'README.md' => 'Hello World' } }
end
trait :allow_runner_registration_token do
after :create do |project|
if project.namespace.namespace_settings.nil?
project.namespace.namespace_settings = create(:namespace_settings, namespace: project.namespace)
end
project.namespace.allow_runner_registration_token = true
end
end
end

View File

@ -8,6 +8,8 @@ RSpec.describe 'User find project file', feature_category: :source_code_manageme
let(:user) { create :user }
let(:project) { create :project, :repository }
global_search_modal_selector = '#super-sidebar-search-modal'
before do
sign_in(user)
project.add_maintainer(user)
@ -16,63 +18,63 @@ RSpec.describe 'User find project file', feature_category: :source_code_manageme
end
def find_file(text)
fill_in 'file_find', with: text
fill_in 'search', with: "~#{text}"
end
def ref_selector_dropdown
find('.ref-selector .gl-button-text')
end
it 'navigates to find file by shortcut', :js do
it 'activates the global search modal by shortcut', :js do
find('body').native.send_key('t')
expect(page).to have_active_sub_navigation('Repository')
expect(page).to have_selector('.file-finder-holder', count: 1)
expect(page).to have_selector(global_search_modal_selector, count: 1)
end
it 'navigates to find file', :js do
click_link 'Find file'
it 'activates the global search modal when find file button is clicked', :js do
click_button 'Find file'
expect(page).to have_active_sub_navigation('Repository')
expect(page).to have_selector('.file-finder-holder', count: 1)
expect(page).to have_selector(global_search_modal_selector, count: 1)
end
it 'searches CHANGELOG file', :js do
click_link 'Find file'
click_button 'Find file'
find_file 'change'
expect(page).to have_content('CHANGELOG')
expect(page).not_to have_content('.gitignore')
expect(page).not_to have_content('VERSION')
page.within(global_search_modal_selector) do
expect(page).to have_content('CHANGELOG')
expect(page).not_to have_content('.gitignore')
expect(page).not_to have_content('VERSION')
end
end
it 'does not find file when search not exist file', :js do
click_link 'Find file'
click_button 'Find file'
find_file 'asdfghjklqwertyuizxcvbnm'
expect(page).not_to have_content('CHANGELOG')
expect(page).not_to have_content('.gitignore')
expect(page).not_to have_content('VERSION')
page.within(global_search_modal_selector) do
expect(page).not_to have_content('CHANGELOG')
expect(page).not_to have_content('.gitignore')
expect(page).not_to have_content('VERSION')
end
end
it 'searches file by partially matches', :js do
click_link 'Find file'
click_button 'Find file'
find_file 'git'
expect(page).to have_content('.gitignore')
expect(page).to have_content('.gitmodules')
expect(page).not_to have_content('CHANGELOG')
expect(page).not_to have_content('VERSION')
page.within(global_search_modal_selector) do
expect(page).to have_content('.gitignore')
expect(page).to have_content('.gitmodules')
expect(page).not_to have_content('CHANGELOG')
expect(page).not_to have_content('VERSION')
end
end
context 'when refs are switched', :js do
before do
click_link 'Find file'
end
specify 'the ref switcher lists all the branches and tags' do
ref = 'add-ipython-files'
expect(ref_selector_dropdown).not_to have_text(ref)
@ -94,7 +96,7 @@ RSpec.describe 'User find project file', feature_category: :source_code_manageme
wait_for_requests
page.within('.ref-selector') do
fill_in _('Switch branch/tag'), with: ref
fill_in _('Search by Git revision'), with: ref
wait_for_requests
select_listbox_item(ref)

View File

@ -10,7 +10,11 @@ RSpec.describe 'Runners', feature_category: :fleet_visibility do
end
context 'with user as project maintainer' do
let_it_be(:project) { create(:project).tap { |project| project.add_maintainer(user) } }
let_it_be(:project) do
create(:project, :allow_runner_registration_token).tap do |project|
project.add_maintainer(user)
end
end
context 'when user views runners page', :js do
before do

View File

@ -2,10 +2,17 @@ import $ from 'jquery';
import { flatten } from 'lodash';
import htmlSnippetsShow from 'test_fixtures/snippets/show.html';
import { Mousetrap } from '~/lib/mousetrap';
import { waitForElement } from '~/lib/utils/dom_utils';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import Shortcuts, { LOCAL_MOUSETRAP_DATA_KEY } from '~/behaviors/shortcuts/shortcuts';
import MarkdownPreview from '~/behaviors/preview_markdown';
const mockSearchInput = document.createElement('input');
jest.mock('~/lib/utils/dom_utils', () => ({
waitForElement: jest.fn(() => Promise.resolve(mockSearchInput)),
}));
describe('Shortcuts', () => {
let shortcuts;
@ -131,6 +138,37 @@ describe('Shortcuts', () => {
});
});
describe('focusSearchFile', () => {
let event;
beforeEach(() => {
jest.spyOn(mockSearchInput, 'dispatchEvent');
event = new KeyboardEvent('keydown', { cancelable: true });
Shortcuts.focusSearchFile(event);
});
it('clicks the super sidebar search button', () => {
expect(HTMLElement.prototype.click).toHaveBeenCalled();
expect(HTMLElement.prototype.click.mock.contexts[0].id).toBe('super-sidebar-search');
});
it('cancels the default behavior of the event', () => {
expect(event.defaultPrevented).toBe(true);
});
it('waits for the input to become available in the DOM', () => {
expect(waitForElement).toHaveBeenCalledWith('#super-sidebar-search-modal #search');
});
it('sets the value of the search input', () => {
expect(mockSearchInput.value).toBe('~');
});
it('dispatches an `input` event on the search input', () => {
expect(mockSearchInput.dispatchEvent).toHaveBeenCalledWith(new Event('input'));
});
});
describe('adding shortcuts', () => {
it('add calls Mousetrap.bind correctly', () => {
const mockCommand = { defaultKeys: ['m'] };

View File

@ -121,7 +121,6 @@ describe('AdminRunnersApp', () => {
wrapper = mountFn(AdminRunnersApp, {
apolloProvider: createMockApollo(handlers, {}, cacheConfig),
propsData: {
registrationToken: mockRegistrationToken,
newRunnerPath,
...props,
},
@ -155,11 +154,19 @@ describe('AdminRunnersApp', () => {
showToast.mockReset();
});
it('shows the runner setup instructions', () => {
createComponent();
it('shows the runner registration token instructions', () => {
createComponent({
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
},
});
expect(findRegistrationDropdown().props('registrationToken')).toBe(mockRegistrationToken);
expect(findRegistrationDropdown().props('type')).toBe(INSTANCE_TYPE);
expect(findRegistrationDropdown().props()).toEqual({
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
type: INSTANCE_TYPE,
});
});
describe('shows total runner counts', () => {
@ -491,7 +498,7 @@ describe('AdminRunnersApp', () => {
});
describe('when no runners are found', () => {
beforeEach(async () => {
beforeEach(() => {
mockRunnersHandler.mockResolvedValue({
data: {
runners: {
@ -500,15 +507,29 @@ describe('AdminRunnersApp', () => {
},
},
});
await createComponent();
});
it('shows no errors', () => {
it('shows no errors', async () => {
await createComponent();
expect(createAlert).not.toHaveBeenCalled();
});
it('shows an empty state', () => {
it('shows an empty state', async () => {
await createComponent();
expect(findRunnerListEmptyState().props()).toEqual({
newRunnerPath,
isSearchFiltered: false,
registrationToken: null,
});
});
it('shows an empty state with a legacy registration token', async () => {
await createComponent({
props: { registrationToken: mockRegistrationToken },
});
expect(findRunnerListEmptyState().props()).toEqual({
newRunnerPath,
isSearchFiltered: false,
@ -518,6 +539,8 @@ describe('AdminRunnersApp', () => {
describe('when a filter is selected by the user', () => {
beforeEach(async () => {
await createComponent();
findRunnerFilteredSearchBar().vm.$emit('input', {
runnerType: null,
membership: DEFAULT_MEMBERSHIP,

View File

@ -9,7 +9,6 @@ import { createWrapper } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { s__ } from '~/locale';
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@ -48,9 +47,7 @@ describe('RegistrationDropdown', () => {
const findTokenDropdownItem = () => wrapper.findComponent(GlDropdownForm);
const findRegistrationToken = () => wrapper.findComponent(RegistrationToken);
const findRegistrationTokenInput = () =>
wrapper.findByLabelText(
`${RegistrationToken.i18n.registrationToken} ${RegistrationDropdown.i18n.supportForRegistrationTokensDeprecated}`,
);
wrapper.findByLabelText(`Registration token Support for registration tokens is deprecated`);
const findTokenResetDropdownItem = () =>
wrapper.findComponent(RegistrationTokenResetDropdownItem);
const findModal = () => wrapper.findComponent(GlModal);
@ -69,7 +66,6 @@ describe('RegistrationDropdown', () => {
const createComponent = ({ props = {}, ...options } = {}, mountFn = shallowMountExtended) => {
wrapper = mountFn(RegistrationDropdown, {
propsData: {
registrationToken: mockRegistrationToken,
type: INSTANCE_TYPE,
...props,
},
@ -80,7 +76,7 @@ describe('RegistrationDropdown', () => {
});
};
const createComponentWithModal = () => {
const createComponentWithModal = (options = {}) => {
const requestHandlers = [
[getRunnerPlatformsQuery, jest.fn().mockResolvedValue(mockRunnerPlatforms)],
[getRunnerSetupInstructionsQuery, jest.fn().mockResolvedValue(mockInstructions)],
@ -92,170 +88,75 @@ describe('RegistrationDropdown', () => {
apolloProvider: createMockApollo(requestHandlers),
// Use `attachTo` to find the modal
attachTo: document.body,
...options,
},
mountExtended,
);
};
it.each`
type | text
${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
${GROUP_TYPE} | ${I18N_REGISTER_GROUP_TYPE}
${PROJECT_TYPE} | ${I18N_REGISTER_PROJECT_TYPE}
`('Dropdown text for type $type is "$text"', ({ type, text }) => {
createComponent({ props: { type } }, mountExtended);
expect(wrapper.text()).toContain(text);
});
it('Passes attributes to dropdown', () => {
createComponent({ attrs: { right: true } });
expect(findDropdown().attributes()).toMatchObject({ right: 'true' });
});
it('Passes default props and attributes to dropdown', () => {
createComponent();
expect(findDropdown().props()).toMatchObject({
category: 'tertiary',
variant: 'default',
});
expect(findDropdown().attributes()).toMatchObject({
toggleclass: 'gl-px-3!',
});
});
describe('Instructions dropdown item', () => {
it('Displays "Show runner" dropdown item', () => {
createComponent();
expect(findRegistrationInstructionsDropdownItem().text()).toBe(
'Show runner installation and registration instructions',
describe('when registration token is disabled', () => {
beforeEach(() => {
createComponent(
{ props: { allowRegistrationToken: false, registrationToken: null } },
mountExtended,
);
});
describe('When the dropdown item is clicked', () => {
beforeEach(async () => {
createComponentWithModal({}, mountExtended);
it('"token is disabled" text is shown', () => {
expect(wrapper.text()).toContain(
'Creating runners with runner registration tokens is disabled',
);
});
await openModal();
});
it('opens the modal with contents', () => {
const modalText = findModalContent();
expect(modalText).toContain('Install a runner');
// Environment selector
expect(modalText).toContain('Environment');
expect(modalText).toContain('Linux macOS Windows Docker Kubernetes');
// Architecture selector
expect(modalText).toContain('Architecture');
expect(modalText).toContain('amd64 amd64 386 arm arm64');
expect(modalText).toContain('Download and install binary');
});
it('registration token is not shown', () => {
expect(findRegistrationToken().exists()).toBe(false);
});
});
describe('Registration token', () => {
it('Displays dropdown form for the registration token', () => {
createComponent();
expect(findTokenDropdownItem().exists()).toBe(true);
});
it('Displays masked value as password input by default', () => {
const mockToken = '0123456789';
describe('when registration token is enabled', () => {
it.each`
type | text
${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
${GROUP_TYPE} | ${I18N_REGISTER_GROUP_TYPE}
${PROJECT_TYPE} | ${I18N_REGISTER_PROJECT_TYPE}
`('Dropdown text for type $type is "$text"', ({ type, text }) => {
createComponent(
{
props: { registrationToken: mockToken },
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
type,
},
},
mountExtended,
);
expect(findRegistrationTokenInput().classes()).toContain('input-copy-show-disc');
});
});
describe('Reset token item', () => {
it('Displays registration token reset item', () => {
createComponent();
expect(findTokenResetDropdownItem().exists()).toBe(true);
expect(wrapper.text()).toContain(text);
});
it.each([INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE])('Set up token reset for %s', (type) => {
createComponent({ props: { type } });
expect(findTokenResetDropdownItem().props('type')).toBe(type);
});
});
describe('Dropdown is expanded', () => {
beforeEach(() => {
createComponent({}, mountExtended);
findDropdownBtn().vm.$emit('click');
});
it('has aria-expanded set to true', () => {
expect(findDropdownBtn().attributes('aria-expanded')).toBe('true');
});
describe('when token is copied', () => {
it('should close dropdown', async () => {
findRegistrationToken().vm.$emit('copy');
await nextTick();
expect(findDropdownBtn().attributes('aria-expanded')).toBe('false');
it('Passes attributes to dropdown', () => {
createComponent({
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
},
attrs: { right: true },
});
});
});
describe('When token is reset', () => {
const newToken = 'mock1';
const resetToken = async () => {
findTokenResetDropdownItem().vm.$emit('tokenReset', newToken);
await nextTick();
};
it('Updates token input', async () => {
createComponent({}, mountExtended);
expect(findRegistrationToken().props('value')).not.toBe(newToken);
await resetToken();
expect(findRegistrationToken().props('value')).toBe(newToken);
expect(findDropdown().attributes()).toMatchObject({ right: 'true' });
});
it('Updates token in modal', async () => {
createComponentWithModal({}, mountExtended);
await openModal();
expect(findModalContent()).toContain(mockRegistrationToken);
await resetToken();
expect(findModalContent()).toContain(newToken);
});
});
describe('When showing a "deprecated" warning', () => {
it('passes deprecated variant props and attributes to dropdown', () => {
createComponent();
it('Passes default props and attributes to dropdown', () => {
createComponent({
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
},
});
expect(findDropdown().props()).toMatchObject({
category: 'tertiary',
variant: 'default',
toggleText: I18N_REGISTER_INSTANCE_TYPE,
textSrOnly: true,
});
expect(findDropdown().attributes()).toMatchObject({
@ -263,30 +164,200 @@ describe('RegistrationDropdown', () => {
});
});
it.each`
type | text
${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
${GROUP_TYPE} | ${I18N_REGISTER_GROUP_TYPE}
${PROJECT_TYPE} | ${I18N_REGISTER_PROJECT_TYPE}
`('dropdown text for type $type is "$text"', ({ type, text }) => {
createComponent({ props: { type } }, mountExtended);
describe('Instructions dropdown item', () => {
it('Displays "Show runner" dropdown item', () => {
createComponent({
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
},
});
expect(wrapper.text()).toContain(text);
expect(findRegistrationInstructionsDropdownItem().text()).toBe(
'Show runner installation and registration instructions',
);
});
describe('When the dropdown item is clicked', () => {
beforeEach(async () => {
createComponentWithModal(
{
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
},
},
mountExtended,
);
await openModal();
});
it('opens the modal with contents', () => {
const modalText = findModalContent();
expect(modalText).toContain('Install a runner');
// Environment selector
expect(modalText).toContain('Environment');
expect(modalText).toContain('Linux macOS Windows Docker Kubernetes');
// Architecture selector
expect(modalText).toContain('Architecture');
expect(modalText).toContain('amd64 amd64 386 arm arm64');
expect(modalText).toContain('Download and install binary');
});
});
});
it('shows warning text', () => {
createComponent({}, mountExtended);
describe('Registration token', () => {
it('Displays dropdown form for the registration token', () => {
createComponent({
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
},
});
const text = wrapper.findByText(s__('Runners|Support for registration tokens is deprecated'));
expect(findTokenDropdownItem().exists()).toBe(true);
});
expect(text.exists()).toBe(true);
it('Displays masked value as password input by default', () => {
const mockToken = '0123456789';
createComponent(
{
props: { allowRegistrationToken: true, registrationToken: mockToken },
},
mountExtended,
);
expect(findRegistrationTokenInput().classes()).toContain('input-copy-show-disc');
});
});
it('button shows ellipsis icon', () => {
createComponent({}, mountExtended);
describe('Reset token item', () => {
describe.each([INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE])(
'Set up token reset for %s',
(type) => {
beforeEach(() => {
createComponent({
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
type,
},
});
});
expect(findDropdownBtn().findComponent(GlIcon).props('name')).toBe('ellipsis_v');
expect(findDropdownBtn().findAllComponents(GlIcon)).toHaveLength(1);
it('Displays registration token reset item', () => {
expect(findTokenResetDropdownItem().props('type')).toBe(type);
});
},
);
});
describe('When token is reset', () => {
const newToken = 'mock1';
const resetToken = async () => {
findTokenResetDropdownItem().vm.$emit('tokenReset', newToken);
await nextTick();
};
it('Updates token input', async () => {
createComponent(
{ props: { allowRegistrationToken: true, registrationToken: mockRegistrationToken } },
mountExtended,
);
expect(findRegistrationToken().props('value')).not.toBe(newToken);
await resetToken();
expect(findRegistrationToken().props('value')).toBe(newToken);
});
it('Updates token in modal', async () => {
createComponentWithModal(
{ props: { allowRegistrationToken: true, registrationToken: mockRegistrationToken } },
mountExtended,
);
await openModal();
expect(findModalContent()).toContain(mockRegistrationToken);
await resetToken();
expect(findModalContent()).toContain(newToken);
});
});
describe('When showing a "deprecated" warning', () => {
it('passes deprecated variant props and attributes to dropdown', () => {
createComponent({
props: { allowRegistrationToken: true, registrationToken: mockRegistrationToken },
});
expect(findDropdown().props()).toMatchObject({
category: 'tertiary',
variant: 'default',
toggleText: I18N_REGISTER_INSTANCE_TYPE,
textSrOnly: true,
});
expect(findDropdown().attributes()).toMatchObject({
toggleclass: 'gl-px-3!',
});
});
it.each`
type | text
${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
${GROUP_TYPE} | ${I18N_REGISTER_GROUP_TYPE}
${PROJECT_TYPE} | ${I18N_REGISTER_PROJECT_TYPE}
`('dropdown text for type $type is "$text"', ({ type, text }) => {
createComponent({ props: { type } }, mountExtended);
expect(wrapper.text()).toContain(text);
});
it('shows warning text', () => {
createComponent(
{
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
},
},
mountExtended,
);
const text = wrapper.findByText('Support for registration tokens is deprecated');
expect(text.exists()).toBe(true);
});
it('button shows ellipsis icon', () => {
createComponent(
{ props: { allowRegistrationToken: true, registrationToken: mockRegistrationToken } },
mountExtended,
);
expect(findDropdownBtn().findComponent(GlIcon).props('name')).toBe('ellipsis_v');
expect(findDropdownBtn().findAllComponents(GlIcon)).toHaveLength(1);
});
});
});
describe('when registration token is hidden due to user permissions', () => {
beforeEach(() => {
createComponent({ props: { allowRegistrationToken: true, registrationToken: null } });
});
it('the component is not shown', () => {
expect(wrapper.html()).toBe('');
});
});
});

View File

@ -479,10 +479,15 @@ describe('GroupRunnersApp', () => {
it('shows the register group runner button', () => {
createComponent({
props: {
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
},
});
expect(findRegistrationDropdown().exists()).toBe(true);
expect(findRegistrationDropdown().props()).toEqual({
allowRegistrationToken: true,
registrationToken: mockRegistrationToken,
type: GROUP_TYPE,
});
});
it('shows the create runner button', () => {
@ -497,15 +502,6 @@ describe('GroupRunnersApp', () => {
});
describe('when user has no permission to register group runner', () => {
it('does not show the register group runner button', () => {
createComponent({
props: {
registrationToken: null,
},
});
expect(findRegistrationDropdown().exists()).toBe(false);
});
it('shows the create runner button', () => {
createComponent({
props: {

View File

@ -1,7 +1,7 @@
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
// eslint-disable-next-line no-restricted-imports
import Vuex from 'vuex';
@ -238,6 +238,15 @@ describe('DynamicField', () => {
});
});
it('emits update event when model is changed', async () => {
createComponent();
findGlFormInput().vm.$emit('input', 'example');
await nextTick();
expect(wrapper.emitted('update')).toEqual([['example']]);
});
describe('label text', () => {
it('renders label with title', () => {
createComponent();

View File

@ -61,6 +61,24 @@ describe('IntegrationSectionCoonfiguration', () => {
});
});
it('emits update event with field when Dynamic text field emits event', () => {
const fields = [{ name: 'username', type: 'text' }];
createComponent({
props: {
fields,
},
});
const dynamicFields = findAllDynamicFields();
const [dynamicField] = dynamicFields.wrappers;
dynamicField.vm.$emit('update', 'example');
expect(wrapper.emitted('update')).toEqual([[{ value: 'example', field: fields[0] }]]);
});
it('does not render DynamicField when field is empty', () => {
createComponent();

View File

@ -1,5 +1,4 @@
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import {
addClassIfElementExists,
canScrollUp,
@ -11,6 +10,7 @@ import {
getParentByTagName,
setAttributes,
replaceCommentsWith,
waitForElement,
} from '~/lib/utils/dom_utils';
const TEST_MARGIN = 5;
@ -285,4 +285,59 @@ describe('DOM Utils', () => {
);
});
});
describe('waitForElement', () => {
const fixture = '<div class="wrapper"></div>';
const mockElementSelector = 'some-selector';
const mockElement = document.createElement('div');
mockElement.classList.add(mockElementSelector);
beforeEach(() => setHTMLFixture(fixture));
afterEach(() => resetHTMLFixture());
it('resolves immediately if element is already in the DOM', async () => {
document.querySelector('.wrapper').appendChild(mockElement);
const result = await waitForElement(`.${mockElementSelector}`);
expect(result).toBe(mockElement);
});
it('resolves after element is added to the DOM', async () => {
const waitForElementPromise = waitForElement(`.${mockElementSelector}`);
document.querySelector('.wrapper').appendChild(mockElement);
const result = await waitForElementPromise;
expect(result).toBe(mockElement);
});
describe('if no element found', () => {
const mockDisconnect = jest.fn();
let OriginalMutationObserver;
const timeoutDelay = 100;
class MutationObserverMock {
constructor() {
this.observe = jest.fn();
this.disconnect = mockDisconnect;
}
}
beforeEach(() => {
OriginalMutationObserver = global.MutationObserver;
global.MutationObserver = MutationObserverMock;
});
afterEach(() => {
global.MutationObserver = OriginalMutationObserver;
});
it('disconnects the observer and rejects the promise after the timeout delay', async () => {
const waitForElementPromise = waitForElement('.some-unavailable-element', timeoutDelay);
jest.advanceTimersByTime(timeoutDelay);
expect(mockDisconnect).toHaveBeenCalled();
await expect(waitForElementPromise).rejects.toMatch('Timeout: Element not found');
});
});
});
});

View File

@ -70,6 +70,8 @@ describe('Container protection rules project settings', () => {
});
describe('table "package protection rules"', () => {
const findTableRowCell = (i, j) => findTableRow(i).findAllByRole('cell').at(j);
it('renders table with Container protection rules', async () => {
createComponent();
@ -79,9 +81,10 @@ describe('Container protection rules project settings', () => {
containerProtectionRuleQueryPayload().data.project.containerRegistryProtectionRules.nodes.forEach(
(protectionRule, i) => {
expect(findTableRow(i).text()).toContain(protectionRule.repositoryPathPattern);
expect(findTableRow(i).text()).toContain('Maintainer');
expect(findTableRow(i).text()).toContain('Maintainer');
expect(findTableRow(i).findAllByRole('cell').length).toBe(3);
expect(findTableRowCell(i, 0).text()).toBe(protectionRule.repositoryPathPattern);
expect(findTableRowCell(i, 1).text()).toBe('Maintainer');
expect(findTableRowCell(i, 2).text()).toBe('Maintainer');
},
);
});

View File

@ -0,0 +1,23 @@
import { initFindFileShortcut } from '~/projects/behaviors';
import Shortcuts from '~/behaviors/shortcuts/shortcuts';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
describe('initFindFileShortcut', () => {
const fixture = '<button class="shortcuts-find-file">Find file</button>';
beforeEach(() => setHTMLFixture(fixture));
afterEach(() => resetHTMLFixture());
it('add a `click` eventListener to the find file button', () => {
const findFileButton = document.querySelector('.shortcuts-find-file');
jest.spyOn(findFileButton, 'addEventListener');
initFindFileShortcut();
expect(findFileButton.addEventListener).toHaveBeenCalledWith(
'click',
Shortcuts.focusSearchFile,
);
});
});

View File

@ -10,6 +10,7 @@ import createRouter from '~/repository/router';
import { updateElementsVisibility } from '~/repository/utils/dom';
import { resetShortcutsForTests } from '~/behaviors/shortcuts';
import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob';
import Shortcuts from '~/behaviors/shortcuts/shortcuts';
import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
import { blobControlsDataMock, refMock } from '../mock_data';
@ -53,8 +54,12 @@ describe('Blob controls component', () => {
beforeEach(() => createComponent());
it('renders a find button with the correct href', () => {
expect(findFindButton().attributes('href')).toBe('find/file.js');
it('triggers a `focusSearchFile` shortcut when the findFile button is clicked', () => {
const findFileButton = findFindButton();
jest.spyOn(Shortcuts, 'focusSearchFile').mockResolvedValue();
findFileButton.vm.$emit('click');
expect(Shortcuts.focusSearchFile).toHaveBeenCalled();
});
it('renders a blame button with the correct href', () => {

View File

@ -33,7 +33,7 @@ describe('GlobalSearchSidebar', () => {
currentScope: jest.fn(() => 'issues'),
};
const createComponent = (initialState = {}) => {
const createComponent = (initialState = {}, glFeatures = {}) => {
const store = new Vuex.Store({
state: {
urlQuery: MOCK_QUERY,
@ -44,6 +44,9 @@ describe('GlobalSearchSidebar', () => {
wrapper = shallowMount(GlobalSearchSidebar, {
store,
provide: {
glFeatures,
},
});
};
@ -105,25 +108,34 @@ describe('GlobalSearchSidebar', () => {
});
describe.each`
scope | searchType | isShown
${'blobs'} | ${SEARCH_TYPE_BASIC} | ${false}
${'blobs'} | ${SEARCH_TYPE_ADVANCED} | ${true}
${'blobs'} | ${SEARCH_TYPE_ZOEKT} | ${true}
`('sidebar blobs scope:', ({ scope, searchType, isShown }) => {
beforeEach(() => {
getterSpies.currentScope = jest.fn(() => scope);
createComponent({
urlQuery: { scope },
searchType,
scope | filter | searchType | searchAddArchivedFilterToZoekt | isShown
${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_BASIC} | ${true} | ${false}
${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_BASIC} | ${false} | ${false}
${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_ADVANCED} | ${true} | ${true}
${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_ADVANCED} | ${false} | ${true}
${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_ZOEKT} | ${true} | ${true}
${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_ZOEKT} | ${false} | ${false}
`(
'sidebar blobs scope:',
({ scope, filter, searchType, searchAddArchivedFilterToZoekt, isShown }) => {
beforeEach(() => {
getterSpies.currentScope = jest.fn(() => scope);
createComponent(
{
urlQuery: { scope },
searchType,
},
{ searchAddArchivedFilterToZoekt },
);
});
});
it(`does ${
isShown ? '' : 'not '
}render filter BlobsFilters when search_type ${searchType}`, () => {
expect(findBlobsFilters().exists()).toBe(isShown);
});
});
it(`does ${
isShown ? '' : 'not '
}render filter BlobsFilters when search_type ${searchType} and searchAddArchivedFilterToZoekt ${searchAddArchivedFilterToZoekt}`, () => {
expect(filter().exists()).toBe(isShown);
});
},
);
describe('with sidebar scope: projects', () => {
beforeEach(() => {

View File

@ -7,7 +7,7 @@ RSpec.describe Types::MergeRequests::MergeabilityCheckStatusEnum, feature_catego
it 'exposes all the existing mergeability check statuses' do
expect(described_class.values.keys).to contain_exactly(
*%w[SUCCESS FAILED INACTIVE]
*%w[SUCCESS FAILED INACTIVE WARNING]
)
end
end

View File

@ -476,7 +476,7 @@ RSpec.describe MarkupHelper, feature_category: :team_planning do
it 'preserves code color scheme' do
object = create_object("```ruby\ndef test\n 'hello world'\nend\n```")
expected = "\n<pre class=\"code highlight js-syntax-highlight language-ruby\" lang=\"ruby\">" \
expected = "\n<pre class=\"code highlight js-syntax-highlight language-ruby\">" \
"<code><span class=\"line\" lang=\"ruby\"><span class=\"k\">def</span> <span class=\"nf\">test</span>...</span>" \
"</code></pre>\n"

View File

@ -23,7 +23,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl
it "highlights as plaintext" do
result = filter('<pre><code>def fun end</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", ""
@ -33,7 +33,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl
it "ignores mermaid blocks" do
result = filter('<pre data-mermaid-style="display" data-canonical-lang="mermaid"><code class="js-render-mermaid">mermaid code</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-mermaid-style="display" data-canonical-lang="mermaid" class="code highlight js-syntax-highlight language-mermaid" lang="mermaid" v-pre="true"><code class="js-render-mermaid"><span id="LC1" class="line" lang="mermaid">mermaid code</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-mermaid-style="display" data-canonical-lang="mermaid" class="code highlight js-syntax-highlight language-mermaid" v-pre="true"><code class="js-render-mermaid"><span id="LC1" class="line" lang="mermaid">mermaid code</span></code></pre><copy-code></copy-code></div>')
end
end
@ -62,7 +62,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl
text = "<div>\n<pre><code>\nsomething\n<pre><code>else\n</code></pre></code></pre>\n</div>"
result = filter(text)
expect(result.to_html.delete("\n")).to eq('<div><div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span><span id="LC2" class="line" lang="plaintext">something</span><span id="LC3" class="line" lang="plaintext">else</span></code></pre><copy-code></copy-code></div></div>')
expect(result.to_html.delete("\n")).to eq('<div><div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span><span id="LC2" class="line" lang="plaintext">something</span><span id="LC3" class="line" lang="plaintext">else</span></code></pre><copy-code></copy-code></div></div>')
end
end
@ -70,7 +70,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl
it "highlights as that language" do
result = filter('<pre data-canonical-lang="ruby"><code>def fun end</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-canonical-lang="ruby" class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-canonical-lang="ruby" class="code highlight js-syntax-highlight language-ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "ruby"
@ -80,7 +80,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl
it "highlights as plaintext" do
result = filter('<pre data-canonical-lang="gnuplot"><code>This is a test</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-canonical-lang="gnuplot" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-canonical-lang="gnuplot" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "gnuplot"
@ -93,7 +93,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl
result = filter(%(<pre data-canonical-lang="#{lang}"><code>This is a test</code></pre>))
copy_code_btn = '<copy-code></copy-code>' unless lang == 'suggestion'
expect(result.to_html.delete("\n")).to eq(%(<div class="gl-relative markdown-code-block js-markdown-code"><pre data-canonical-lang="#{lang}" class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>#{copy_code_btn}</div>))
expect(result.to_html.delete("\n")).to eq(%(<div class="gl-relative markdown-code-block js-markdown-code"><pre data-canonical-lang="#{lang}" class="code highlight js-syntax-highlight language-#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>#{copy_code_btn}</div>))
end
include_examples "XSS prevention", lang
@ -105,13 +105,13 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl
it "includes it in the highlighted code block" do
result = filter('<pre data-sourcepos="1:1-3:3" data-canonical-lang="plaintext"><code>This is a test</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos="1:1-3:3" data-canonical-lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos="1:1-3:3" data-canonical-lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
end
it "escape sourcepos metadata to prevent XSS" do
result = filter('<pre data-sourcepos="&#34;%22 href=&#34;x&#34;></pre><base href=http://unsafe-website.com/><pre x=&#34;"><code></code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos=\'"%22 href="x"&gt;&lt;/pre&gt;&lt;base href=http://unsafe-website.com/&gt;&lt;pre x="\' class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos=\'"%22 href="x"&gt;&lt;/pre&gt;&lt;base href=http://unsafe-website.com/&gt;&lt;pre x="\' class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre><copy-code></copy-code></div>')
end
end
@ -125,7 +125,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl
it "highlights as plaintext" do
result = filter('<pre data-canonical-lang="ruby"><code>This is a test</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-canonical-lang="ruby" class="code highlight js-syntax-highlight" lang="" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-canonical-lang="ruby" class="code highlight js-syntax-highlight" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "ruby"

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ClickHouse::WriteBuffer, :clean_gitlab_redis_shared_state, feature_category: :database do
describe '.write_event' do
subject(:write_event) { described_class.write_event(event_hash) }
let(:event_hash) { { foo: 'bar' } }
it 'saves ClickHouse event to Redis' do
expect do
write_event
end.to change {
Gitlab::Redis::SharedState.with do |redis|
redis.lrange(described_class::BUFFER_KEY, 0, 10)
end
}.from([]).to([event_hash.to_json])
end
end
end

View File

@ -98,7 +98,7 @@ module Gitlab
<div>
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-canonical-lang="mypre" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code></code></pre>
<pre data-canonical-lang="mypre" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
</div>
@ -369,7 +369,7 @@ module Gitlab
<div>
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-canonical-lang="js" class="code highlight js-syntax-highlight language-javascript" lang="javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<pre data-canonical-lang="js" class="code highlight js-syntax-highlight language-javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<copy-code></copy-code>
</div>
</div>
@ -399,7 +399,7 @@ module Gitlab
<div>class.cpp</div>
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-canonical-lang="c++" class="code highlight js-syntax-highlight language-cpp" lang="cpp" v-pre="true"><code><span id="LC1" class="line" lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span></span>
<pre data-canonical-lang="c++" class="code highlight js-syntax-highlight language-cpp" v-pre="true"><code><span id="LC1" class="line" lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span></span>
<span id="LC2" class="line" lang="cpp"></span>
<span id="LC3" class="line" lang="cpp"><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span></span>
<span id="LC4" class="line" lang="cpp"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">"*"</span><span class="o">&lt;&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span></span>
@ -457,7 +457,7 @@ module Gitlab
stem:[2+2] is 4
MD
expect(render(input, context)).to include('<pre data-math-style="display" class="code math js-render-math" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">eta_x gamma</span></code></pre>')
expect(render(input, context)).to include('<pre data-math-style="display" class="code math js-render-math" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">eta_x gamma</span></code></pre>')
expect(render(input, context)).to include('<p><code data-math-style="inline" class="code math js-render-math">2+2</code> is 4</p>')
end
end

View File

@ -40,6 +40,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::ComponentUsage, feature_category: :p
let(:value) { 1 } # Default resource_type
end
it 'creates a component usage record' do
expect { perform }.to change { Ci::Catalog::Resources::Components::Usage.count }.by(1)
end
context 'when component usage has already been recorded', :freeze_time do
it 'does not create a component usage record' do
step.perform!
expect { perform }.not_to change { Ci::Catalog::Resources::Components::Usage.count }
end
end
context 'when the FF `ci_track_catalog_component_usage` is disabled' do
before do
stub_feature_flags(ci_track_catalog_component_usage: false)
@ -50,6 +62,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::ComponentUsage, feature_category: :p
perform
end
it 'does not create a component usage record' do
expect { perform }.not_to change { Ci::Catalog::Resources::Components::Usage.count }
end
end
end
end

View File

@ -2,8 +2,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_default: :keep do
let_it_be(:project) { create_default(:project).freeze }
RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_default: :keep, feature_category: :continuous_integration do
let_it_be(:project) { create_default(:project, :allow_runner_registration_token).freeze }
let_it_be_with_reload(:build) { create(:ci_build, :success) }
let(:trace) { described_class.new(build) }

View File

@ -12,9 +12,14 @@ RSpec.describe Gitlab::Doctor::ResetTokens, feature_category: :fleet_visibility
let_it_be(:functional_project) { create(:project).tap(&:runners_token) }
let_it_be(:functional_group) { create(:group).tap(&:runners_token) }
let(:broken_project) { create(:project).tap { |project| project.update_columns(runners_token_encrypted: 'aaa') } }
let(:broken_project) do
create(:project, :allow_runner_registration_token).tap do |project|
project.update_columns(runners_token_encrypted: 'aaa')
end
end
let(:project_with_cipher_error) do
create(:project).tap do |project|
create(:project, :allow_runner_registration_token).tap do |project|
project.update_columns(
runners_token_encrypted: '|rXs75DSHXPE9MGAIgyxcut8pZc72gaa/2ojU0GS1+R+cXNqkbUB13Vb5BaMwf47d98980fc1')
end

View File

@ -489,7 +489,11 @@ RSpec.describe Group, feature_category: :groups_and_projects do
it_behaves_like 'a BulkUsersByEmailLoad model'
it_behaves_like 'ensures runners_token is prefixed', :group
it_behaves_like 'ensures runners_token is prefixed' do
subject(:record) do
create(:group, namespace_settings: create(:namespace_settings, allow_runner_registration_token: true))
end
end
context 'after initialized' do
it 'has a group_feature' do

View File

@ -14,7 +14,13 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
it_behaves_like 'having unique enum values'
it_behaves_like 'ensures runners_token is prefixed', :project
context 'when runner registration is allowed' do
let_it_be(:project) { create(:project, :allow_runner_registration_token) }
it_behaves_like 'ensures runners_token is prefixed' do
subject(:record) { project }
end
end
describe 'associations' do
it { is_expected.to belong_to(:organization) }
@ -1143,15 +1149,24 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
describe 'project token' do
it 'sets an random token if none provided' do
project = FactoryBot.create(:project, runners_token: '')
expect(project.runners_token).not_to eq('')
describe 'runner registration token' do
let(:project) { create(:project, :allow_runner_registration_token, runners_token: initial_token) }
context 'when no token provided' do
let(:initial_token) { '' }
it 'sets an random token' do
expect(project.runners_token).not_to be_nil
expect(project.runners_token).not_to eq(initial_token)
end
end
it 'does not set an random token if one provided' do
project = FactoryBot.create(:project, runners_token: "#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}my-token")
expect(project.runners_token).to eq("#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}my-token")
context 'when initial token exists' do
let(:initial_token) { "#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}my-token" }
it 'does not set an random token' do
expect(project.runners_token).to eq(initial_token)
end
end
end

Some files were not shown because too many files have changed in this diff Show More