Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
336b65a1c7
commit
2389653f0e
|
|
@ -264,7 +264,20 @@ include:
|
|||
- remote: 'https://gitlab.com/gitlab-org/frontend/untamper-my-lockfile/-/raw/main/templates/merge_request_pipelines.yml'
|
||||
rules:
|
||||
- <<: *if-not-security-canonical-sync
|
||||
- local: .gitlab/ci/gitlab-com/*.gitlab-ci.yml
|
||||
- local: .gitlab/ci/includes/gitlab-com/*.gitlab-ci.yml
|
||||
rules:
|
||||
- if: '$CI_SERVER_HOST == "gitlab.com"'
|
||||
- if: '$CI_SERVER_HOST == "jihulab.com"'
|
||||
- local: .gitlab/ci/includes/as-if-jh.gitlab-ci.yml
|
||||
rules:
|
||||
# Only run as-if-jh triggerred pipelines for gitlab.com/gitlab-org/gitlab MRs that don't target stable branches
|
||||
# and that don't have the quarantine or pipeline:expedite labels.
|
||||
- if: '$CI_PROJECT_URL != "https://gitlab.com/gitlab-org/gitlab"'
|
||||
when: never
|
||||
- if: '$CI_MERGE_REQUEST_ID == null'
|
||||
when: never
|
||||
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee|-jh)?$/'
|
||||
when: never
|
||||
- if: '$CI_MERGE_REQUEST_LABELS =~ /quarantine/ || $CI_MERGE_REQUEST_LABELS =~ /pipeline:expedite/'
|
||||
when: never
|
||||
- when: always
|
||||
|
|
|
|||
|
|
@ -462,9 +462,10 @@ lib/gitlab/checks/**
|
|||
# Begin rake-managed-docs-block
|
||||
/doc/administration/analytics/ @lciutacu
|
||||
/doc/administration/application_settings_cache.md @jglassman1
|
||||
/doc/administration/audit_event_reports.md @eread
|
||||
/doc/administration/audit_event_schema.md @eread
|
||||
/doc/administration/audit_event_streaming/ @eread
|
||||
/doc/administration/audit_events.md @eread
|
||||
/doc/administration/audit_reports.md @eread
|
||||
/doc/administration/audit_event_types.md @eread
|
||||
/doc/administration/auditor_users.md @jglassman1
|
||||
/doc/administration/auth/ @jglassman1
|
||||
/doc/administration/backup_restore/ @axil
|
||||
|
|
@ -562,6 +563,7 @@ lib/gitlab/checks/**
|
|||
/doc/administration/settings/project_integration_management.md @eread @ashrafkhamis
|
||||
/doc/administration/settings/push_event_activities_limit.md @msedlakjakubowski
|
||||
/doc/administration/settings/rate_limit_on_issues_creation.md @msedlakjakubowski
|
||||
/doc/administration/settings/rate_limit_on_members_api.md @lciutacu
|
||||
/doc/administration/settings/rate_limit_on_notes_creation.md @msedlakjakubowski
|
||||
/doc/administration/settings/rate_limit_on_pipelines_creation.md @marcel.amirault @lyspin
|
||||
/doc/administration/settings/rate_limit_on_projects_api.md @lciutacu
|
||||
|
|
@ -814,6 +816,7 @@ lib/gitlab/checks/**
|
|||
/doc/integration/akismet.md @phillipwells
|
||||
/doc/integration/arkose.md @phillipwells
|
||||
/doc/integration/datadog.md @eread @ashrafkhamis
|
||||
/doc/integration/diffblue_cover.md @marcel.amirault @lyspin
|
||||
/doc/integration/external-issue-tracker.md @eread @ashrafkhamis
|
||||
/doc/integration/gitpod.md @ashrafkhamis
|
||||
/doc/integration/gmail_action_buttons_for_gitlab.md @eread @ashrafkhamis
|
||||
|
|
@ -872,6 +875,7 @@ lib/gitlab/checks/**
|
|||
/doc/user/compliance/compliance_center/ @eread
|
||||
/doc/user/compliance/index.md @eread
|
||||
/doc/user/custom_roles.md @jglassman1
|
||||
/doc/user/custom_roles/ @jglassman1
|
||||
/doc/user/discussions/ @aqualls
|
||||
/doc/user/emoji_reactions.md @msedlakjakubowski
|
||||
/doc/user/enterprise_user/ @jglassman1
|
||||
|
|
@ -885,7 +889,6 @@ lib/gitlab/checks/**
|
|||
/doc/user/group/epics/ @msedlakjakubowski
|
||||
/doc/user/group/import/ @eread @ashrafkhamis
|
||||
/doc/user/group/index.md @lciutacu
|
||||
/doc/user/group/insights/ @lciutacu
|
||||
/doc/user/group/issues_analytics/ @lciutacu
|
||||
/doc/user/group/iterations/ @msedlakjakubowski
|
||||
/doc/user/group/manage.md @lciutacu
|
||||
|
|
@ -935,6 +938,8 @@ lib/gitlab/checks/**
|
|||
/doc/user/project/index.md @lciutacu
|
||||
/doc/user/project/insights/ @lciutacu
|
||||
/doc/user/project/integrations/ @eread @ashrafkhamis
|
||||
/doc/user/project/integrations/beyond_identity.md @msedlakjakubowski
|
||||
/doc/user/project/integrations/git_guardian.md @msedlakjakubowski
|
||||
/doc/user/project/issues/csv_import.md @eread @ashrafkhamis
|
||||
/doc/user/project/members/ @lciutacu
|
||||
/doc/user/project/merge_requests/ @aqualls
|
||||
|
|
@ -945,6 +950,8 @@ lib/gitlab/checks/**
|
|||
/doc/user/project/merge_requests/reviews/data_usage.md @sselhorn
|
||||
/doc/user/project/merge_requests/squash_and_merge.md @msedlakjakubowski
|
||||
/doc/user/project/merge_requests/status_checks.md @eread
|
||||
/doc/user/project/ml/experiment_tracking/ @sselhorn
|
||||
/doc/user/project/ml/model_registry/ @sselhorn
|
||||
/doc/user/project/organize_work_with_projects.md @lciutacu
|
||||
/doc/user/project/releases/ @phillipwells
|
||||
/doc/user/project/releases/release_evidence.md @eread
|
||||
|
|
@ -958,6 +965,7 @@ lib/gitlab/checks/**
|
|||
/doc/user/project/settings/migrate_projects.md @lciutacu
|
||||
/doc/user/project/settings/project_access_tokens.md @jglassman1
|
||||
/doc/user/project/settings/project_features_permissions.md @lciutacu
|
||||
/doc/user/project/troubleshooting.md @lciutacu
|
||||
/doc/user/project/use_project_as_go_package.md @lciutacu
|
||||
/doc/user/project/web_ide/ @ashrafkhamis
|
||||
/doc/user/project/working_with_projects.md @lciutacu
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ prepare-as-if-foss-branch:
|
|||
before_script:
|
||||
- git clone --single-branch --branch master "${FOSS_REPOSITORY}" gitlab-foss
|
||||
- git -C gitlab-foss checkout -b "${AS_IF_FOSS_BRANCH}" master
|
||||
- git -C gitlab-foss rev-parse HEAD
|
||||
- rm -r .git/
|
||||
- mv gitlab-foss/.git .
|
||||
- rm -r gitlab-foss
|
||||
|
|
@ -29,7 +30,9 @@ prepare-as-if-foss-branch:
|
|||
- rm -f CHANGELOG-EE.md
|
||||
- rm -f changelogs/*-ee.md
|
||||
- git add -A
|
||||
- git commit -m 'Update from merge request' # TODO: Mark which SHA we add
|
||||
# --allow-empty accounts for the edge case where FOSS matchess EE repository
|
||||
# and a merge request only contains EE related changes.
|
||||
- git commit -m 'Update from merge request' --allow-empty # TODO: Mark which SHA we add
|
||||
- git push -f "${FOSS_REPOSITORY}" "${AS_IF_FOSS_BRANCH}"
|
||||
|
||||
prepare-as-if-foss-env:
|
||||
|
|
|
|||
|
|
@ -514,3 +514,8 @@
|
|||
curl -f --header "Private-Token: ${PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE}" "${url}" --create-dirs --output scripts/utils.sh
|
||||
- source scripts/utils.sh
|
||||
- run_timed_command "download_files ${FILES_TO_DOWNLOAD}"
|
||||
|
||||
.with_secret:
|
||||
id_tokens:
|
||||
GCP_ID_TOKEN:
|
||||
aud: https://iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_FEDERATION_POOL_ID}/providers/${GCP_WORKLOAD_IDENTITY_FEDERATION_PROVIDER_ID}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
.as-if-jh-sandbox-variables:
|
||||
variables:
|
||||
AS_IF_JH_BRANCH: "as-if-jh/${CI_COMMIT_REF_NAME}"
|
||||
JH_MIRROR_REPOSITORY: "https://dummy:${ADD_JH_FILES_TOKEN}@gitlab.com/gitlab-org/gitlab-jh-mirrors/gitlab.git"
|
||||
SANDBOX_REPOSITORY: "https://dummy:${AS_IF_JH_TOKEN}@gitlab.com/gitlab-org-sandbox/gitlab-jh-validation.git"
|
||||
|
||||
.shared-as-if-jh:
|
||||
|
|
@ -14,12 +13,20 @@
|
|||
add-jh-files:
|
||||
extends:
|
||||
- .shared-as-if-jh
|
||||
- .with_secret
|
||||
- .as-if-jh:rules:prepare-as-if-jh
|
||||
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}
|
||||
stage: prepare
|
||||
needs: []
|
||||
secrets:
|
||||
ADD_JH_FILES_TOKEN:
|
||||
gcp_secret_manager:
|
||||
name: ADD_JH_FILES_TOKEN
|
||||
token: $GCP_ID_TOKEN
|
||||
before_script:
|
||||
- source ./scripts/utils.sh
|
||||
- export ADD_JH_FILES_TOKEN="$(cat ${ADD_JH_FILES_TOKEN})"
|
||||
- export JH_MIRROR_REPOSITORY="https://dummy:${ADD_JH_FILES_TOKEN}@gitlab.com/gitlab-org/gitlab-jh-mirrors/gitlab.git"
|
||||
- source ./scripts/setup/as-if-jh.sh
|
||||
- install_gitlab_gem
|
||||
script:
|
||||
|
|
@ -44,11 +44,6 @@ dont-interrupt-me:
|
|||
script:
|
||||
- !reference [.base-script, script]
|
||||
- rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~zoekt --tag ~click_house"
|
||||
artifacts:
|
||||
expire_in: 7d
|
||||
paths:
|
||||
- "${RSPEC_MATCHING_TESTS_FOSS_PATH}"
|
||||
- tmp/capybara/
|
||||
|
||||
<% if rspec_files_per_test_level[:migration][:files].size > 0 %>
|
||||
rspec migration foss-impact:
|
||||
|
|
|
|||
|
|
@ -623,7 +623,7 @@
|
|||
- "vendor/assets/javascripts/**/*"
|
||||
|
||||
.feature-flag-development-config-patterns: &feature-flag-development-config-patterns
|
||||
- "{,ee/,jh/}config/feature_flags/{development,ops}/*.yml"
|
||||
- "{,ee/,jh/}config/feature_flags/**/*.yml"
|
||||
|
||||
.glfm-patterns: &glfm-patterns
|
||||
- ".gitlab/ci/rules.gitlab-ci.yml"
|
||||
|
|
@ -661,17 +661,6 @@
|
|||
- <<: *if-jh
|
||||
when: never
|
||||
|
||||
.as-if-jh-default-exclusion-rules:
|
||||
rules:
|
||||
- if: '$ADD_JH_FILES_TOKEN == null'
|
||||
when: never
|
||||
- <<: *if-security-merge-request
|
||||
when: never
|
||||
- <<: *if-merge-request-targeting-stable-branch
|
||||
when: never
|
||||
- <<: *if-merge-request-labels-pipeline-expedite
|
||||
when: never
|
||||
|
||||
.rails:rules:run-search-tests:
|
||||
rules:
|
||||
- !reference [".rails:rules:default-branch-schedule-nightly--code-backstage-ee-only", rules]
|
||||
|
|
@ -3179,10 +3168,8 @@
|
|||
##################
|
||||
.as-if-jh:rules:prepare-as-if-jh:
|
||||
rules:
|
||||
- !reference [".strict-ee-only-rules", rules]
|
||||
- !reference [".as-if-jh-default-exclusion-rules", rules]
|
||||
- <<: *if-merge-request-labels-as-if-jh
|
||||
- <<: *if-dot-com-gitlab-org-merge-request
|
||||
- <<: *if-merge-request
|
||||
changes: *feature-flag-development-config-patterns
|
||||
|
||||
# This rule should share the same logic with .as-if-jh:rules:prepare-as-if-jh
|
||||
|
|
@ -3204,8 +3191,6 @@
|
|||
# dependencies changes.
|
||||
.as-if-jh:rules:sync-as-if-jh:
|
||||
rules:
|
||||
- !reference [".strict-ee-only-rules", rules]
|
||||
- !reference [".as-if-jh-default-exclusion-rules", rules]
|
||||
- <<: *if-merge-request-labels-as-if-jh
|
||||
changes: *dependency-patterns
|
||||
# Ideally, we should be able to do this:
|
||||
|
|
@ -3216,11 +3201,9 @@
|
|||
# Because the jobs using this need jobs using the preparation rules
|
||||
.as-if-jh:rules:start-as-if-jh:
|
||||
rules:
|
||||
- !reference [".strict-ee-only-rules", rules]
|
||||
- !reference [".as-if-jh-default-exclusion-rules", rules]
|
||||
- <<: *if-merge-request-labels-as-if-jh
|
||||
allow_failure: true # See https://gitlab.com/gitlab-org/gitlab/-/issues/351136
|
||||
- <<: *if-dot-com-gitlab-org-merge-request
|
||||
- <<: *if-merge-request
|
||||
changes: *feature-flag-development-config-patterns
|
||||
allow_failure: true # See https://gitlab.com/gitlab-org/gitlab/-/issues/351136
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
af2fbf3d304a0cd637f8b9ea47817b8c9b6f109b
|
||||
042a35ce7e9bd624b1f777d36eb3660e20f563e2
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -300,7 +300,7 @@ gem 'redis-actionpack', '~> 5.4.0' # rubocop:todo Gemfile/MissingFeatureCategory
|
|||
gem 'discordrb-webhooks', '~> 3.4', require: false, feature_category: :integrations
|
||||
|
||||
# Jira integration
|
||||
gem 'jira-ruby', '~> 2.1.4', feature_category: :integrations
|
||||
gem 'jira-ruby', '~> 2.3.0', feature_category: :integrations
|
||||
gem 'atlassian-jwt', '~> 0.2.0', feature_category: :integrations
|
||||
|
||||
# Slack integration
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@
|
|||
{"name":"jaeger-client","version":"1.1.0","platform":"ruby","checksum":"cb5e9b9bbee6ee8d6a82d03d947a5b04543d8c0a949c22e484254f18d8a458a8"},
|
||||
{"name":"jaro_winkler","version":"1.5.4","platform":"java","checksum":"0454333a50b44a09745878bfe57859893631ff7dfe48c029827894944514fe7c"},
|
||||
{"name":"jaro_winkler","version":"1.5.4","platform":"ruby","checksum":"50c3e83c5a9e8769c1cf5b73c8b51bb6eebbf8852a0ee53bf6ad6e4dc63414f9"},
|
||||
{"name":"jira-ruby","version":"2.1.4","platform":"ruby","checksum":"4267c095cac8323b9eef3ba866eb28bb1388b7623a5abb60c1e7caf12d4adb9e"},
|
||||
{"name":"jira-ruby","version":"2.3.0","platform":"ruby","checksum":"abf26e6bff4a8ea40bae06f7df6276a5776905c63fb2070934823ca54f62eb62"},
|
||||
{"name":"jmespath","version":"1.6.2","platform":"ruby","checksum":"238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1"},
|
||||
{"name":"js_regex","version":"3.8.0","platform":"ruby","checksum":"7934bcdd5a0e6d5af4a520288fd4684a02a472ae55831d9178ccaf82356344b5"},
|
||||
{"name":"json","version":"2.6.3","platform":"java","checksum":"ea8c47427a2c876121b9a0ab53043ca390013a76374330eabd923bd81914e563"},
|
||||
|
|
|
|||
|
|
@ -969,7 +969,7 @@ GEM
|
|||
opentracing (~> 0.3)
|
||||
thrift
|
||||
jaro_winkler (1.5.4)
|
||||
jira-ruby (2.1.4)
|
||||
jira-ruby (2.3.0)
|
||||
activesupport
|
||||
atlassian-jwt
|
||||
multipart-post
|
||||
|
|
@ -1986,7 +1986,7 @@ DEPENDENCIES
|
|||
ipaddr (~> 1.2.5)
|
||||
ipaddress (~> 0.8.3)
|
||||
ipynbdiff!
|
||||
jira-ruby (~> 2.1.4)
|
||||
jira-ruby (~> 2.3.0)
|
||||
js_regex (~> 3.8)
|
||||
json (~> 2.6.3)
|
||||
json_schemer (~> 0.2.18)
|
||||
|
|
|
|||
|
|
@ -38,9 +38,12 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['toggleDiscussion']),
|
||||
...mapActions('diffs', ['toggleFileDiscussion']),
|
||||
isExpanded(discussion) {
|
||||
return this.shouldCollapseDiscussions ? discussion.expanded : true;
|
||||
return this.shouldCollapseDiscussions ? discussion.expandedOnDiff : true;
|
||||
},
|
||||
toggleVisibility(discussion) {
|
||||
this.toggleFileDiscussion(discussion);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -59,11 +62,11 @@ export default {
|
|||
<ul :data-discussion-id="discussion.id" class="notes">
|
||||
<template v-if="shouldCollapseDiscussions">
|
||||
<button
|
||||
v-if="discussion.expanded"
|
||||
v-if="discussion.expandedOnDiff"
|
||||
class="diff-notes-collapse js-diff-notes-toggle"
|
||||
type="button"
|
||||
:aria-label="__('Show comments')"
|
||||
@click="toggleDiscussion({ discussionId: discussion.id })"
|
||||
@click="toggleVisibility(discussion)"
|
||||
>
|
||||
<gl-icon name="collapse" class="collapse-icon" />
|
||||
</button>
|
||||
|
|
@ -73,7 +76,7 @@ export default {
|
|||
:is-resolved="discussion.resolved"
|
||||
size="sm"
|
||||
class="js-diff-notes-toggle gl-translate-x-n50"
|
||||
@click="toggleDiscussion({ discussionId: discussion.id })"
|
||||
@click="toggleVisibility(discussion)"
|
||||
/>
|
||||
</template>
|
||||
<noteable-discussion
|
||||
|
|
|
|||
|
|
@ -213,7 +213,6 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
...mapActions('diffs', [
|
||||
'toggleFileDiscussions',
|
||||
'toggleFileDiscussionWrappers',
|
||||
'toggleFullDiff',
|
||||
'setCurrentFileHash',
|
||||
|
|
|
|||
|
|
@ -586,29 +586,10 @@ export const loadCollapsedDiff = ({ commit, getters, state }, { file, params = {
|
|||
|
||||
/**
|
||||
* Toggles the file discussions after user clicked on the toggle discussions button.
|
||||
*
|
||||
* Gets the discussions for the provided diff.
|
||||
*
|
||||
* If all discussions are expanded, it will collapse all of them
|
||||
* If all discussions are collapsed, it will expand all of them
|
||||
* If some discussions are open and others closed, it will expand the closed ones.
|
||||
*
|
||||
* @param {Object} diff
|
||||
* @param {Object} discussion
|
||||
*/
|
||||
export const toggleFileDiscussions = ({ getters, dispatch }, diff) => {
|
||||
const discussions = getters.getDiffFileDiscussions(diff);
|
||||
const shouldCloseAll = getters.diffHasAllExpandedDiscussions(diff);
|
||||
const shouldExpandAll = getters.diffHasAllCollapsedDiscussions(diff);
|
||||
|
||||
discussions.forEach((discussion) => {
|
||||
const data = { discussionId: discussion.id };
|
||||
|
||||
if (shouldCloseAll) {
|
||||
dispatch('collapseDiscussion', data, { root: true });
|
||||
} else if (shouldExpandAll || (!shouldCloseAll && !shouldExpandAll && !discussion.expanded)) {
|
||||
dispatch('expandDiscussion', data, { root: true });
|
||||
}
|
||||
});
|
||||
export const toggleFileDiscussion = ({ commit }, discussion) => {
|
||||
commit(types.TOGGLE_FILE_DISCUSSION_EXPAND, discussion);
|
||||
};
|
||||
|
||||
export const toggleFileDiscussionWrappers = ({ commit }, diff) => {
|
||||
|
|
@ -1116,3 +1097,7 @@ export const unpinFile = ({ getters, commit }) => {
|
|||
newUrl.hash = '';
|
||||
window.history.replaceState(null, undefined, newUrl);
|
||||
};
|
||||
|
||||
export const toggleAllDiffDiscussions = ({ commit, getters }) => {
|
||||
commit(types.SET_EXPAND_ALL_DIFF_DISCUSSIONS, !getters.allDiffDiscussionsExpanded);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,6 +71,25 @@ export const diffHasExpandedDiscussions = () => (diff) => {
|
|||
return diffFileDiscussionsExpanded || diffLineDiscussionsExpanded;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if every diff has every discussion open
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export const allDiffDiscussionsExpanded = (state) => {
|
||||
return state.diffFiles.every((diff) => {
|
||||
const highlightedLines = diff[INLINE_DIFF_LINES_KEY];
|
||||
if (highlightedLines.length) {
|
||||
return highlightedLines
|
||||
.filter((l) => l.discussions.length >= 1)
|
||||
.every((l) => l.discussionsExpanded);
|
||||
}
|
||||
if (diff.viewer.name === 'image') {
|
||||
return diff.discussions.every((discussion) => discussion.expandedOnDiff);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the diff has any discussion
|
||||
* @param {Boolean} diff
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export const ADD_CONTEXT_LINES = 'ADD_CONTEXT_LINES';
|
|||
export const ADD_COLLAPSED_DIFFS = 'ADD_COLLAPSED_DIFFS';
|
||||
export const RENDER_FILE = 'RENDER_FILE';
|
||||
export const SET_LINE_DISCUSSIONS_FOR_FILE = 'SET_LINE_DISCUSSIONS_FOR_FILE';
|
||||
export const TOGGLE_FILE_DISCUSSION_EXPAND = 'TOGGLE_FILE_DISCUSSION_EXPAND';
|
||||
export const REMOVE_LINE_DISCUSSIONS_FOR_FILE = 'REMOVE_LINE_DISCUSSIONS_FOR_FILE';
|
||||
export const TOGGLE_FOLDER_OPEN = 'TOGGLE_FOLDER_OPEN';
|
||||
export const TREE_ENTRY_DIFF_LOADING = 'TREE_ENTRY_DIFF_LOADING';
|
||||
|
|
@ -51,6 +52,7 @@ export const SET_DIFF_FILE_VIEWER = 'SET_DIFF_FILE_VIEWER';
|
|||
|
||||
export const SET_SHOW_SUGGEST_POPOVER = 'SET_SHOW_SUGGEST_POPOVER';
|
||||
|
||||
export const SET_EXPAND_ALL_DIFF_DISCUSSIONS = 'SET_EXPAND_ALL_DIFF_DISCUSSIONS';
|
||||
export const TOGGLE_LINE_DISCUSSIONS = 'TOGGLE_LINE_DISCUSSIONS';
|
||||
export const DISABLE_VIRTUAL_SCROLLING = 'DISABLE_VIRTUAL_SCROLLING';
|
||||
|
||||
|
|
|
|||
|
|
@ -173,7 +173,6 @@ export default {
|
|||
|
||||
[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { discussion, diffPositionByLineCode, hash }) {
|
||||
const { latestDiff } = state;
|
||||
|
||||
const originalStartLineCode = discussion.original_position?.line_range?.start?.line_code;
|
||||
const positionType = discussion.position?.position_type;
|
||||
const discussionLineCodes = [
|
||||
|
|
@ -182,7 +181,11 @@ export default {
|
|||
...(discussion.line_codes || []),
|
||||
];
|
||||
const fileHash = discussion.diff_file?.file_hash;
|
||||
const lineCheck = (line) =>
|
||||
|
||||
const isHashTargeted = (discussionItem) =>
|
||||
discussionItem.notes && discussionItem.notes.some((note) => hash === `note_${note.id}`);
|
||||
|
||||
const isTargetLine = (line) =>
|
||||
discussionLineCodes.some(
|
||||
(discussionLineCode) =>
|
||||
line.line_code === discussionLineCode &&
|
||||
|
|
@ -192,65 +195,40 @@ export default {
|
|||
latestDiff,
|
||||
}),
|
||||
);
|
||||
const mapDiscussions = (line, extraCheck = () => true) => ({
|
||||
...line,
|
||||
discussions: extraCheck()
|
||||
? line.discussions &&
|
||||
line.discussions
|
||||
.filter(() => !line.discussions.some(({ id }) => discussion.id === id))
|
||||
.concat(lineCheck(line) ? discussion : line.discussions)
|
||||
: [],
|
||||
});
|
||||
|
||||
const setDiscussionsExpanded = (line) => {
|
||||
const isLineNoteTargeted =
|
||||
line.discussions &&
|
||||
line.discussions.some(
|
||||
(disc) => disc.notes && disc.notes.find((note) => hash === `note_${note.id}`),
|
||||
);
|
||||
|
||||
return {
|
||||
...line,
|
||||
discussionsExpanded:
|
||||
line.discussionsExpanded ||
|
||||
(line.discussions && line.discussions.length
|
||||
? line.discussions.some((disc) => !disc.resolved) || isLineNoteTargeted
|
||||
: false),
|
||||
};
|
||||
const isExpandedDiscussion = (discussionItem) => {
|
||||
return !discussionItem.resolved || isHashTargeted(discussionItem);
|
||||
};
|
||||
|
||||
state.diffFiles.forEach((file) => {
|
||||
if (file.file_hash === fileHash) {
|
||||
if (positionType === FILE_DIFF_POSITION_TYPE) {
|
||||
const newDiscussions = (file.discussions || [])
|
||||
.filter((d) => d.id !== discussion.id)
|
||||
.concat(discussion);
|
||||
const addDiscussion = (discussions) =>
|
||||
discussions.filter(({ id }) => discussion.id !== id).concat(discussion);
|
||||
|
||||
Object.assign(file, {
|
||||
discussions: newDiscussions,
|
||||
});
|
||||
} else {
|
||||
if (file[INLINE_DIFF_LINES_KEY].length) {
|
||||
file[INLINE_DIFF_LINES_KEY].forEach((line) => {
|
||||
Object.assign(
|
||||
line,
|
||||
setDiscussionsExpanded(lineCheck(line) ? mapDiscussions(line) : line),
|
||||
);
|
||||
});
|
||||
}
|
||||
const file = state.diffFiles.find((diff) => diff.file_hash === fileHash);
|
||||
// a file batch might not be loaded yet when we try to add a discussion
|
||||
if (!file) return;
|
||||
const diffLines = file[INLINE_DIFF_LINES_KEY];
|
||||
|
||||
if (!file[INLINE_DIFF_LINES_KEY].length) {
|
||||
const newDiscussions = (file.discussions || [])
|
||||
.filter((d) => d.id !== discussion.id)
|
||||
.concat(discussion);
|
||||
if (diffLines.length && positionType !== FILE_DIFF_POSITION_TYPE) {
|
||||
const line = diffLines.find(isTargetLine);
|
||||
const discussions = addDiscussion(line.discussions || []);
|
||||
Object.assign(line, {
|
||||
discussions,
|
||||
discussionsExpanded: line.discussionsExpanded || discussions.some(isExpandedDiscussion),
|
||||
});
|
||||
} else {
|
||||
Object.assign(discussion, { expandedOnDiff: isExpandedDiscussion(discussion) });
|
||||
Object.assign(file, {
|
||||
discussions: addDiscussion(file.discussions || []),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
Object.assign(file, {
|
||||
discussions: newDiscussions,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
[types.TOGGLE_FILE_DISCUSSION_EXPAND](state, discussion) {
|
||||
Object.assign(discussion, { expandedOnDiff: !discussion.expandedOnDiff });
|
||||
const fileHash = discussion.diff_file.file_hash;
|
||||
const diff = state.diffFiles.find((f) => f.file_hash === fileHash);
|
||||
// trigger Vue reactivity
|
||||
Object.assign(diff, { discussions: [...diff.discussions] });
|
||||
},
|
||||
|
||||
[types.REMOVE_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash, lineCode }) {
|
||||
|
|
@ -278,6 +256,27 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
[types.SET_EXPAND_ALL_DIFF_DISCUSSIONS](state, expanded) {
|
||||
const lineHasDiscussion = (line) => Boolean(line.discussions?.length);
|
||||
state.diffFiles.forEach((file) => {
|
||||
const highlightedLines = file[INLINE_DIFF_LINES_KEY];
|
||||
if (highlightedLines.length) {
|
||||
const discussionLines = highlightedLines.filter(lineHasDiscussion);
|
||||
discussionLines.forEach(({ line_code }) => {
|
||||
updateLineInFile(file, line_code, (line) => {
|
||||
Object.assign(line, { discussionsExpanded: expanded });
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const discussions = file.discussions.map((discussion) => {
|
||||
Object.assign(discussion, { expandedOnDiff: expanded });
|
||||
return discussion;
|
||||
});
|
||||
Object.assign(file, { discussions });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
[types.TOGGLE_FOLDER_OPEN](state, path) {
|
||||
state.treeEntries[path].opened = !state.treeEntries[path].opened;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,3 +21,11 @@ export async function fetchMrMetadata({ state, commit }) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const toggleAllVisibleDiscussions = ({ getters, dispatch }) => {
|
||||
if (getters.isDiffsPage) {
|
||||
dispatch('diffs/toggleAllDiffDiscussions');
|
||||
} else {
|
||||
dispatch('toggleAllDiscussions');
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,4 +7,11 @@ export default {
|
|||
isLoggedIn(state, getters) {
|
||||
return Boolean(getters.getUserData.id);
|
||||
},
|
||||
isDiffsPage(state) {
|
||||
return state.activeTab === 'diffs';
|
||||
},
|
||||
allVisibleDiscussionsExpanded(state, getters) {
|
||||
if (getters.isDiffsPage) return getters['diffs/allDiffDiscussionsExpanded'];
|
||||
return getters.allDiscussionsExpanded;
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ export default {
|
|||
:file-hash="discussion.diff_file.file_hash"
|
||||
:show-comment-icon="true"
|
||||
:should-toggle-discussion="false"
|
||||
badge-class="image-comment-badge gl-text-gray-500"
|
||||
badge-class="image-comment-badge gl-text-purple-500 gl-bg-white gl-rounded-full gl-border-white gl-border-1 gl-border-solid gl-pointer-events-none gl-shadow-md"
|
||||
/>
|
||||
</template>
|
||||
</diff-viewer>
|
||||
|
|
|
|||
|
|
@ -42,15 +42,15 @@ export default {
|
|||
'resolvableDiscussionsCount',
|
||||
'unresolvedDiscussionsCount',
|
||||
'allResolvableDiscussions',
|
||||
'allVisibleDiscussionsExpanded',
|
||||
]),
|
||||
allResolved() {
|
||||
return this.unresolvedDiscussionsCount === 0;
|
||||
},
|
||||
allExpanded() {
|
||||
return this.allResolvableDiscussions.every((discussion) => discussion.expanded);
|
||||
},
|
||||
toggleThreadsLabel() {
|
||||
return this.allExpanded ? __('Collapse all threads') : __('Expand all threads');
|
||||
return !this.allVisibleDiscussionsExpanded
|
||||
? __('Show all comments')
|
||||
: __('Hide all comments');
|
||||
},
|
||||
nextUnresolvedDiscussionShortcutKey() {
|
||||
return shouldDisableShortcuts() ? null : keysFor(MR_NEXT_UNRESOLVED_DISCUSSION)[0];
|
||||
|
|
@ -85,7 +85,7 @@ export default {
|
|||
const options = [
|
||||
{
|
||||
text: this.toggleThreadsLabel,
|
||||
action: this.handleExpandDiscussions,
|
||||
action: this.toggleAllVisibleDiscussions,
|
||||
extraAttrs: {
|
||||
'data-testid': 'toggle-all-discussions-btn',
|
||||
},
|
||||
|
|
@ -109,13 +109,7 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setExpandDiscussions']),
|
||||
handleExpandDiscussions() {
|
||||
this.setExpandDiscussions({
|
||||
discussionIds: this.allResolvableDiscussions.map((discussion) => discussion.id),
|
||||
expanded: !this.allExpanded,
|
||||
});
|
||||
},
|
||||
...mapActions(['toggleAllVisibleDiscussions']),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -466,7 +466,7 @@ export default {
|
|||
:href="author.path"
|
||||
:data-user-id="author.id"
|
||||
:data-username="author.username"
|
||||
class="js-user-link"
|
||||
class="js-user-link gl-relative"
|
||||
>
|
||||
<gl-avatar
|
||||
:src="author.avatar_url"
|
||||
|
|
|
|||
|
|
@ -82,8 +82,9 @@ export const setNotesFetchedState = ({ commit }, state) =>
|
|||
|
||||
export const toggleDiscussion = ({ commit }, data) => commit(types.TOGGLE_DISCUSSION, data);
|
||||
|
||||
export const setExpandDiscussions = ({ commit }, { discussionIds, expanded }) => {
|
||||
commit(types.SET_EXPAND_DISCUSSIONS, { discussionIds, expanded });
|
||||
export const toggleAllDiscussions = ({ commit, getters }) => {
|
||||
const expanded = getters.allDiscussionsExpanded;
|
||||
commit(types.SET_EXPAND_ALL_DISCUSSIONS, !expanded);
|
||||
};
|
||||
|
||||
export const fetchDiscussions = (
|
||||
|
|
|
|||
|
|
@ -380,3 +380,7 @@ export const getFetchDiscussionsConfig = (state, getters) => {
|
|||
}
|
||||
return defaultConfig;
|
||||
};
|
||||
|
||||
export const allDiscussionsExpanded = (state) => {
|
||||
return state.discussions.every((discussion) => discussion.expanded);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export const COLLAPSE_DISCUSSION = 'COLLAPSE_DISCUSSION';
|
|||
export const EXPAND_DISCUSSION = 'EXPAND_DISCUSSION';
|
||||
export const TOGGLE_DISCUSSION = 'TOGGLE_DISCUSSION';
|
||||
export const SET_EXPAND_DISCUSSIONS = 'SET_EXPAND_DISCUSSIONS';
|
||||
export const SET_EXPAND_ALL_DISCUSSIONS = 'SET_EXPAND_ALL_DISCUSSIONS';
|
||||
export const UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS = 'UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS';
|
||||
export const SET_CURRENT_DISCUSSION_ID = 'SET_CURRENT_DISCUSSION_ID';
|
||||
export const SET_DISCUSSIONS_SORT = 'SET_DISCUSSIONS_SORT';
|
||||
|
|
|
|||
|
|
@ -233,6 +233,12 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
[types.SET_EXPAND_ALL_DISCUSSIONS](state, expanded) {
|
||||
state.discussions.forEach((discussion) => {
|
||||
Object.assign(discussion, { expanded });
|
||||
});
|
||||
},
|
||||
|
||||
[types.SET_RESOLVING_DISCUSSION](state, isResolving) {
|
||||
state.isResolvingDiscussion = isResolving;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -514,7 +514,8 @@ module ApplicationSettingsHelper
|
|||
:ci_max_total_yaml_size_bytes,
|
||||
:project_jobs_api_rate_limit,
|
||||
:security_txt_content,
|
||||
:allow_project_creation_for_guest_and_below
|
||||
:allow_project_creation_for_guest_and_below,
|
||||
:downstream_pipeline_trigger_limit_per_project_user_sha
|
||||
].tap do |settings|
|
||||
next if Gitlab.com?
|
||||
|
||||
|
|
|
|||
|
|
@ -597,11 +597,13 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord
|
|||
:sidekiq_job_limiter_compression_threshold_bytes,
|
||||
:sidekiq_job_limiter_limit_bytes,
|
||||
:terminal_max_session_time,
|
||||
:users_get_by_id_limit
|
||||
:users_get_by_id_limit,
|
||||
:downstream_pipeline_trigger_limit_per_project_user_sha
|
||||
end
|
||||
|
||||
jsonb_accessor :rate_limits,
|
||||
members_delete_limit: [:integer, { default: 60 }]
|
||||
members_delete_limit: [:integer, { default: 60 }],
|
||||
downstream_pipeline_trigger_limit_per_project_user_sha: [:integer, { default: 0 }]
|
||||
|
||||
validates :rate_limits, json_schema: { filename: "application_setting_rate_limits" }
|
||||
|
||||
|
|
|
|||
|
|
@ -280,7 +280,8 @@ module ApplicationSettingImplementation
|
|||
security_txt_content: nil,
|
||||
allow_project_creation_for_guest_and_below: true,
|
||||
enable_member_promotion_management: false,
|
||||
security_approval_policies_limit: 5
|
||||
security_approval_policies_limit: 5,
|
||||
downstream_pipeline_trigger_limit_per_project_user_sha: 0
|
||||
}.tap do |hsh|
|
||||
hsh.merge!(non_production_defaults) unless Rails.env.production?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ module Ci
|
|||
end
|
||||
|
||||
def by_scope(relation, scope)
|
||||
if scope == :namespaces && Feature.enabled?(:ci_guard_for_catalog_resource_scope, current_user)
|
||||
if scope == :namespaces
|
||||
relation.visible_to_user(current_user)
|
||||
else
|
||||
relation.public_or_visible_to_user(current_user)
|
||||
|
|
|
|||
|
|
@ -13,5 +13,15 @@ module Members
|
|||
|
||||
validates :new_access_level, presence: true
|
||||
validates :old_access_level, presence: true
|
||||
validate :validate_unique_pending_approval, on: [:create, :update]
|
||||
|
||||
private
|
||||
|
||||
def validate_unique_pending_approval
|
||||
if pending? && self.class.where(member_id: member_id, member_namespace_id: member_namespace_id,
|
||||
new_access_level: new_access_level, status: 0).exists?
|
||||
errors.add(:base, 'A pending approval for the same member, namespace, and access level already exists.')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@
|
|||
module Ci
|
||||
# Enqueues the downstream pipeline worker.
|
||||
class TriggerDownstreamPipelineService
|
||||
# This is a temporary constant. It may be converted into an application setting
|
||||
# in the future. See https://gitlab.com/gitlab-org/gitlab/-/issues/425941.
|
||||
DOWNSTREAM_PIPELINE_TRIGGER_LIMIT_PER_PROJECT_USER_SHA = 200
|
||||
|
||||
def initialize(bridge)
|
||||
@bridge = bridge
|
||||
@current_user = bridge.user
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@
|
|||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "Number of project or group members a user can delete per minute."
|
||||
},
|
||||
"downstream_pipeline_trigger_limit_per_project_user_sha": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "Maximum number of downstream pipelines triggered in a project per user"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@
|
|||
= f.number_field :ci_max_includes, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= s_('AdminSettings|The maximum number of included files per pipeline.')
|
||||
.form-group
|
||||
= f.label :downstream_pipeline_trigger_limit_per_project_user_sha, s_('AdminSettings|Maximum downstream pipelines triggered in a project per user'), class: 'label-bold'
|
||||
= f.number_field :downstream_pipeline_trigger_limit_per_project_user_sha, min: 0, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= s_('AdminSettings|The maximum number of downstream pipelines triggered in a project per user.')
|
||||
.form-group
|
||||
= f.label :ci_config_path, _('Default CI/CD configuration file'), class: 'label-bold'
|
||||
= f.text_field :default_ci_config_path, class: 'form-control gl-form-input', placeholder: '.gitlab-ci.yml'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
= render_if_exists 'notify/address_new_reviewer_with_diff_summary'
|
||||
|
||||
%p
|
||||
= change_reviewer_notification_text(@merge_request.reviewers, @previous_reviewers, :strong)
|
||||
= change_reviewer_notification_text(@merge_request.reviewers, @previous_reviewers)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
%p
|
||||
= html_escape(s_('Notify|%{name} requested a new review on %{mr_link}.')) % {name: sanitize_name(@updated_by.name), mr_link: merge_request_reference_link(@merge_request).html_safe}
|
||||
- long_mr = '%{reference} %{mrtitle}' % { reference: @merge_request.to_reference, mrtitle: @merge_request.title }
|
||||
- mr_url = merge_request_url(@merge_request)
|
||||
|
||||
%h4{ style: 'margin-bottom: 0' }
|
||||
= s_('Notify|Review requested')
|
||||
%p{ style: 'margin-top: 0' }
|
||||
= html_escape(s_('Notify|You were added as a reviewer on %{long_mr} by %{name}.')) % {name: sanitize_name(@updated_by.name), long_mr: long_mr}
|
||||
= render_if_exists 'notify/diff_summary'
|
||||
%p
|
||||
%a{ href: mr_url, target: "_blank", rel: "noopener noreferrer nofollow", style: "-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; font-size: 14px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color: #ffffff; text-decoration: none; border-radius: 4px; -webkit-border-radius: 4px; background-color: #1f75cb; display: inline-block; padding: 8px 12px; box-shadow: inset 0 0 0 1px #1068bf" }
|
||||
= s_('Notify|Review changes')
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: ci_guard_for_catalog_resource_scope
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137015
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/432219
|
||||
milestone: '16.7'
|
||||
type: development
|
||||
group: group::pipeline authoring
|
||||
default_enabled: true
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: usage_data_api
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41301
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267114
|
||||
milestone: '13.4'
|
||||
type: ops
|
||||
group: group::analytics instrumentation
|
||||
default_enabled: true
|
||||
|
|
@ -816,9 +816,9 @@ Gitlab.ee do
|
|||
Settings.cron_jobs['sync_service_token_worker'] ||= {}
|
||||
Settings.cron_jobs['sync_service_token_worker']['cron'] ||= "#{rand(60)} #{rand(5..6)} * * * UTC"
|
||||
Settings.cron_jobs['sync_service_token_worker']['job_class'] = '::Ai::SyncServiceTokenWorker'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_empty_embeddings_records_worker'] ||= {}
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_empty_embeddings_records_worker']['cron'] ||= '0 5 * * 1,2,3,4,5'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_empty_embeddings_records_worker']['job_class'] ||= 'Llm::Embedding::GitlabDocumentation::CreateEmptyEmbeddingsRecordsWorker'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_embeddings_records_worker'] ||= {}
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_embeddings_records_worker']['cron'] ||= '0 5 * * 1,2,3,4,5'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_embeddings_records_worker']['job_class'] ||= 'Llm::Embedding::GitlabDocumentation::CreateEmbeddingsRecordsWorker'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_cleanup_previous_versions_records_worker'] ||= {}
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_cleanup_previous_versions_records_worker']['cron'] ||= '0 0 * * *'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_cleanup_previous_versions_records_worker']['job_class'] ||= 'Llm::Embedding::GitlabDocumentation::CleanupPreviousVersionsRecordsWorker'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
- title: "Removal of tags from small SaaS runners on Linux"
|
||||
removal_milestone: "17.0"
|
||||
announcement_milestone: "16.9"
|
||||
breaking_change: true
|
||||
reporter: gabrielengel_gl
|
||||
stage: Verify
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/30829
|
||||
manual_task: true
|
||||
body: | # (required) Don't change this line.
|
||||
Due to historical reasons, small Linux SaaS Runners had a lot of tags attached because they were used as labels. We want to streamline the tag to just use `saas-linux-small-amd64` and be consistent across all SaaS runners.
|
||||
|
||||
We are deprecating the tags: `docker`, `east-c`, `gce`, `git-annex`, `linux`, `mongo`, `mysql`, `postgres`, `ruby`, `shared`.
|
||||
|
||||
For more information, see [Removing tags from our small SaaS runner on Linux](https://about.gitlab.com/blog/2023/08/15/removing-tags-from-small-saas-runner-on-linux/).
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
- title: "Upgrading the operating system version of GitLab SaaS runners on Linux"
|
||||
removal_milestone: "17.0"
|
||||
announcement_milestone: "16.9"
|
||||
breaking_change: true
|
||||
reporter: gabrielengel_gl
|
||||
stage: Verify
|
||||
issue_url: https://gitlab.com/gitlab-org/ci-cd/shared-runners/infrastructure/-/issues/60
|
||||
manual_task: true
|
||||
body: | # (required) Don't change this line.
|
||||
GitLab is upgrading the container-optimized operating system (COS) of the ephemeral VMs used to execute jobs for SaaS runners on Linux.
|
||||
That COS upgrade includes a Docker Engine upgrade from Version 19.03.15 to Version 23.0.5, which introduces a known compatibility issue.
|
||||
|
||||
Docker-in-Docker prior to version 20.10 or Kaniko images older than v1.9.0, will be unable to detect the container runtime and fail.
|
||||
|
||||
For more information, see [Upgrading the operating system version of our SaaS runners on Linux](https://about.gitlab.com/blog/2023/10/04/updating-the-os-version-of-saas-runners-on-linux/).
|
||||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Join table relating packages_packages with ci_pipelines
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19796
|
||||
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:
|
||||
project_id:
|
||||
references: projects
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Composer package metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30448
|
||||
milestone: '13.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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Conan package metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16418
|
||||
milestone: '12.5'
|
||||
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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Debian registry group-level architectures
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51265
|
||||
milestone: '13.8'
|
||||
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: distribution_id
|
||||
table: packages_debian_project_distributions
|
||||
sharding_key: project_id
|
||||
belongs_to: distribution
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Debian package project-level distribution components
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51732
|
||||
milestone: '13.9'
|
||||
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: distribution_id
|
||||
table: packages_debian_project_distributions
|
||||
sharding_key: project_id
|
||||
belongs_to: distribution
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Debian project-level distribution keys
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60993
|
||||
milestone: '14.0'
|
||||
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: distribution_id
|
||||
table: packages_debian_project_distributions
|
||||
sharding_key: project_id
|
||||
belongs_to: distribution
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Debian package publications relating distributions to packages
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52916
|
||||
milestone: '13.9'
|
||||
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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Join table between packages_packages and packages_dependencies
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20549
|
||||
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:
|
||||
project_id:
|
||||
references: projects
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Maven package metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6607
|
||||
milestone: '11.3'
|
||||
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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Npm package metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73639
|
||||
milestone: '14.5'
|
||||
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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Nuget package metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30994
|
||||
milestone: '13.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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Package registry file links and file metadata for all package types
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6607
|
||||
milestone: '11.3'
|
||||
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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: PyPI package metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27632
|
||||
milestone: '13.0'
|
||||
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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Rpm package metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96019
|
||||
milestone: '15.4'
|
||||
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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Ruby gems metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52639
|
||||
milestone: '13.9'
|
||||
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: package_id
|
||||
table: packages_packages
|
||||
sharding_key: project_id
|
||||
belongs_to: package
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddConditionalUniqueIndexToMemberApprovals < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.10'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'unique_member_approvals_on_pending_status'
|
||||
|
||||
def up
|
||||
add_concurrent_index :member_approvals, [:member_id, :member_namespace_id, :new_access_level],
|
||||
unique: true, where: "status = 0", name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :member_approvals, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
f8ae8294d45a5d796a86d629bef9b25142895b497db778c694d8573338a274d2
|
||||
|
|
@ -36549,6 +36549,8 @@ CREATE UNIQUE INDEX unique_instance_google_cloud_logging_configurations ON audit
|
|||
|
||||
CREATE UNIQUE INDEX unique_instance_google_cloud_logging_configurations_name ON audit_events_instance_google_cloud_logging_configurations USING btree (name);
|
||||
|
||||
CREATE UNIQUE INDEX unique_member_approvals_on_pending_status ON member_approvals USING btree (member_id, member_namespace_id, new_access_level) WHERE (status = 0);
|
||||
|
||||
CREATE UNIQUE INDEX unique_merge_request_diff_llm_summaries_on_mr_diff_id ON merge_request_diff_llm_summaries USING btree (merge_request_diff_id);
|
||||
|
||||
CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON merge_request_metrics USING btree (merge_request_id);
|
||||
|
|
|
|||
|
|
@ -205,6 +205,18 @@ The default is `150`.
|
|||
1. Change the value of **Maximum includes**.
|
||||
1. Select **Save changes** for the changes to take effect.
|
||||
|
||||
## Maximum downstream pipelines triggered per project
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144077) in GitLab 16.10 [with feature flag](../feature_flags.md) named `ci_rate_limit_downstream_pipelines`. Disabled by default.
|
||||
|
||||
The maximum number of [downstream pipelines](../../ci/pipelines/downstream_pipelines.md) per project per user can be set at the instance level.
|
||||
The default is `0` (no restriction).
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||
1. Select **Settings > CI/CD**.
|
||||
1. Change the value of **Maximum downstream pipelines triggered in a project per user**.
|
||||
1. Select **Save changes** for the changes to take effect.
|
||||
|
||||
## Default CI/CD configuration file
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18073) in GitLab 12.5.
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ With this method:
|
|||
- Set up an internet-facing reverse proxy in front of your self-managed instance. To secure this proxy further, only allow inbound
|
||||
traffic from [Atlassian IP addresses](https://support.atlassian.com/organization-administration/docs/ip-addresses-and-domains-for-atlassian-cloud-products/#Outgoing-Connections).
|
||||
- Add [GitLab IP addresses](../../user/gitlab_com/index.md#ip-range) to the allowlist of your firewall.
|
||||
- The Jira user that installs and configures the GitLab for Jira Cloud app must meet certain [requirements](#jira-user-requirements).
|
||||
- The Jira user that installs and configures the app must meet certain [requirements](#jira-user-requirements).
|
||||
|
||||
### Set up your instance
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ To support your self-managed instance with Jira Cloud, do one of the following:
|
|||
|
||||
- The instance must be publicly available.
|
||||
- You must set up [OAuth authentication](#set-up-oauth-authentication).
|
||||
- The Jira user that installs and configures the GitLab for Jira Cloud app must meet certain [requirements](#jira-user-requirements).
|
||||
- The Jira user that installs and configures the app must meet certain [requirements](#jira-user-requirements).
|
||||
|
||||
### Install the app in development mode
|
||||
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ Depending on how you installed the app, you might want to check the following:
|
|||
1. Select all checkboxes, then select **Next**.
|
||||
1. Enter your **GitLab instance URL**, then select **Save**.
|
||||
|
||||
If this method does not work, [submit a support ticket](https://support.gitlab.com/hc/en-us/requests/new) if you're a Premium or Ultimate customer
|
||||
and provide your GitLab instance URL and Jira URL. GitLab Support can try to run the following scripts to resolve the issue:
|
||||
If this method does not work, [submit a support ticket](https://support.gitlab.com/hc/en-us/requests/new) if you're a Premium or Ultimate customer.
|
||||
Provide your GitLab instance URL and Jira URL. GitLab Support can try to run the following scripts to resolve the issue:
|
||||
|
||||
```ruby
|
||||
# Check if GitLab.com can connect to the self-managed instance
|
||||
|
|
|
|||
|
|
@ -281,7 +281,8 @@ Example response:
|
|||
"bulk_import_max_download_file_size": 5120,
|
||||
"project_jobs_api_rate_limit": 600,
|
||||
"security_txt_content": null,
|
||||
"bulk_import_concurrent_pipeline_batch_limit": 25
|
||||
"bulk_import_concurrent_pipeline_batch_limit": 25,
|
||||
"downstream_pipeline_trigger_limit_per_project_user_sha": 0
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -390,6 +391,7 @@ listed in the descriptions of the relevant settings.
|
|||
| `domain_denylist_enabled` | boolean | no | (**If enabled, requires:** `domain_denylist`) Allows blocking sign-ups from emails from specific domains. |
|
||||
| `domain_denylist` | array of strings | no | Users with email addresses that match these domains **cannot** sign up. Wildcards allowed. Use separate lines for multiple entries. For example: `domain.com`, `*.domain.com`. |
|
||||
| `domain_allowlist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is `null`, meaning there is no restriction. |
|
||||
| `downstream_pipeline_trigger_limit_per_project_user_sha` | integer | no | Rate limit creation of downstream pipelines. Default: `0`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144077) in GitLab 16.10 with a [flag](../administration/feature_flags.md) named `ci_rate_limit_downstream_pipelines`. Disabled by default. |
|
||||
| `dsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded DSA key. Default is `0` (no restriction). `-1` disables DSA keys. |
|
||||
| `ecdsa_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA key. Default is `0` (no restriction). `-1` disables ECDSA keys. |
|
||||
| `ecdsa_sk_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA_SK key. Default is `0` (no restriction). `-1` disables ECDSA_SK keys. |
|
||||
|
|
|
|||
|
|
@ -240,3 +240,6 @@ In progress.
|
|||
- 2022-06-31: [Pipeline partitioning design](pipeline_partitioning.md) document [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87683) merged.
|
||||
- 2022-09-01: Engineering effort started to implement partitioning.
|
||||
- 2022-11-01: The fastest growing CI table partitioned: `ci_builds_metadata`.
|
||||
- 2023-06-30: The second largest table partitioned: `ci_builds`.
|
||||
- 2023-12-12: `ci_builds` and `ci_builds_metadata` growth is stopped by writing data to new partitions.
|
||||
- 2024-02-05: `ci_pipeline_variables` is partitioned.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ multiple GitLab deployments, instances, and cells. We use it as an umbrella term
|
|||
embeddings are stored in the `vertex_gitlab_docs` database table in the
|
||||
`embeddings` database. The embeddings search is done in Postgres using the
|
||||
`vector` extension. The vertex embeddings database is updated based on the
|
||||
latest version of GitLab documentation on daily basis by running `Llm::Embedding::GitlabDocumentation::CreateEmptyEmbeddingsRecordsWorker` as a cronjob.
|
||||
latest version of GitLab documentation on a daily basis by running `Llm::Embedding::GitlabDocumentation::CreateEmbeddingsRecordsWorker` as a cronjob.
|
||||
- **Golden Questions**: a small subset of the types of questions we think a user
|
||||
should be able to ask GitLab Duo Chat. Used to generate data for Chat evaluation.
|
||||
[Questions for Chat Beta](https://gitlab.com/groups/gitlab-org/-/epics/10550#what-the-user-can-ask).
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ DETAILS:
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- You must have [site administrator](https://support.atlassian.com/user-management/docs/give-users-admin-permissions/#Make-someone-a-site-admin) access to the Jira instance.
|
||||
- Your network must allow inbound and outbound connections between GitLab and Jira.
|
||||
- You must meet certain [Jira user requirements](../../administration/settings/jira_cloud_app.md#jira-user-requirements).
|
||||
|
||||
To install the GitLab for Jira Cloud app:
|
||||
|
||||
|
|
@ -75,16 +75,16 @@ DETAILS:
|
|||
Prerequisites:
|
||||
|
||||
- You must have at least the Maintainer role for the GitLab group.
|
||||
- The Jira user that installs and configures the GitLab for Jira Cloud app must meet certain [requirements](../../administration/settings/jira_cloud_app.md#jira-user-requirements).
|
||||
- You must meet certain [Jira user requirements](../../administration/settings/jira_cloud_app.md#jira-user-requirements).
|
||||
|
||||
You can sync data from GitLab to Jira by linking the GitLab for Jira Cloud app to one or more GitLab groups.
|
||||
To configure the GitLab for Jira Cloud app:
|
||||
|
||||
1. In Jira, on the top bar, select **Apps > Manage your apps**.
|
||||
1. Expand **GitLab for Jira**.
|
||||
1. Expand **GitLab for Jira (GitLab.com)**.
|
||||
1. Select **Get started**.
|
||||
1. Optional. Select **Change GitLab version** to set the GitLab instance to use with Jira.
|
||||
1. Select **Sign into GitLab**.
|
||||
1. Optional. To set the GitLab instance to use with Jira, select **Change GitLab version**.
|
||||
1. Select **Sign in to GitLab**.
|
||||
1. For a list of groups you can link to, select **Link groups**.
|
||||
1. To link to a group, select **Link**.
|
||||
|
||||
|
|
|
|||
|
|
@ -21,18 +21,17 @@ To create Jira credentials, here's what we're going to do:
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- You must have [site administrator](https://support.atlassian.com/user-management/docs/give-users-admin-permissions/#Make-someone-a-site-admin) access to the Jira instance.
|
||||
- You must have at least the `Jira Administrators` [global permission](https://confluence.atlassian.com/adminjiraserver/managing-global-permissions-938847142.html).
|
||||
|
||||
## Create a Jira user
|
||||
|
||||
To create a Jira user:
|
||||
|
||||
1. Sign in to your Jira instance as an administrator.
|
||||
1. On the top bar, in the upper-right corner, select **Administration** (**{settings}**) > **User management**.
|
||||
1. [Create a new user account](https://confluence.atlassian.com/adminjiraserver/create-edit-or-remove-a-user-938847025.html#Create,edit,orremoveauser-CreateusersmanuallyinJira) with write access to your Jira projects.
|
||||
|
||||
Alternatively, you can use an existing user account, provided the user belongs to a Jira group that has been granted
|
||||
the **Administer Projects** [permission scheme](#create-a-permission-scheme-for-the-group).
|
||||
the `Administer Projects` [permission scheme](#create-a-permission-scheme-for-the-group).
|
||||
|
||||
- In **Email address**, enter a valid email address.
|
||||
- In **Username**, enter `gitlab`.
|
||||
|
|
@ -45,7 +44,6 @@ Now that you've created a user named `gitlab`, it's time to create a group for t
|
|||
|
||||
To create a Jira group for the user:
|
||||
|
||||
1. Sign in to your Jira instance as an administrator.
|
||||
1. On the top bar, in the upper-right corner, select **Administration** (**{settings}**) > **User management**.
|
||||
1. On the left sidebar, select **Groups**.
|
||||
1. In the **Add group** section, enter a name for the group (for example,
|
||||
|
|
@ -65,7 +63,6 @@ it's time to create a permission scheme for the group.
|
|||
|
||||
To create a permission scheme for the group:
|
||||
|
||||
1. Sign in to your Jira instance as an administrator.
|
||||
1. On the top bar, in the upper-right corner, select **Administration** (**{settings}**) > **Issues**.
|
||||
1. On the left sidebar, select **Permission schemes**.
|
||||
1. Select **Add permission scheme**.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Fulfillment
|
||||
group: Purchase
|
||||
group: Provision
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Fulfillment
|
||||
group: Purchase
|
||||
group: Subscription Management
|
||||
description: Options for accessing GitLab.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Fulfillment
|
||||
group: Purchase
|
||||
group: Subscription Management
|
||||
description: Education, Open Source, Startups.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Fulfillment
|
||||
group: Purchase
|
||||
group: Subscription Management
|
||||
description: Payment and company details.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Fulfillment
|
||||
group: Purchase
|
||||
group: Subscription Management
|
||||
description: Seat usage, compute minutes, storage limits, renewal info.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
@ -387,6 +387,28 @@ To add a secondary contact for your subscription:
|
|||
[Customers Portal](https://customers.gitlab.com/customers/sign_in) for the user you want to add.
|
||||
1. [Create a ticket with the Support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293). Include any relevant material in your request.
|
||||
|
||||
## GitLab Duo Pro
|
||||
|
||||
Increase developer productivity across the software development lifecycle. Refer to [GitLab Duo](../../user/ai_features.md) for more information.
|
||||
|
||||
### Purchase additional GitLab Duo Pro seats
|
||||
|
||||
If you're using GitLab SaaS, you can purchase additional seats for the GitLab Duo Pro product.
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. Select **Settings > Usage Quotas**.
|
||||
1. Select **Duo Pro**.
|
||||
1. Select **Add seats**. GitLab redirects you to the Customers Portal.
|
||||
1. Enter the desired quantity of GitLab Duo Pro seats. Mind that it should not be higher than the amount of seats in your group namespace main subscription.
|
||||
1. In the **Billing information** section select the payment method from the dropdown list.
|
||||
1. Select the **Privacy Policy** and **Terms of Service** checkbox.
|
||||
1. Select **Purchase seats**.
|
||||
1. Switch back to the GitLab SaaS tab and refresh the page.
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
|
||||
After your payment is processed, the additional seats are available for your group namespace.
|
||||
|
||||
## Compute
|
||||
|
||||
Compute is the resource consumed when running [pipelines](../../ci/pipelines/index.md)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Fulfillment
|
||||
group: Purchase
|
||||
group: Subscription Management
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Fulfillment
|
||||
group: Purchase
|
||||
group: Subscription Management
|
||||
description: Billing examples.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Fulfillment
|
||||
group: Purchase
|
||||
group: Provision
|
||||
description: Seat assignment, GitLab Duo Pro add-on
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
@ -21,12 +21,10 @@ add-ons can be assigned to billable users only.
|
|||
Prerequisites:
|
||||
|
||||
- You must purchase the GitLab Duo Pro add-on from the [GitLab Sales Team](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/).
|
||||
- For self-managed and GitLab Dedicated, the GitLab Duo Pro add-on is available for GitLab 16.8 and later only.
|
||||
|
||||
After you purchase GitLab Duo Pro, you can assign seats to billable users to grant access to the add-on.
|
||||
|
||||
NOTE:
|
||||
For self-managed and GitLab Dedicated, the GitLab Duo Pro add-on is available for GitLab 16.8 and later only.
|
||||
|
||||
### For GitLab.com
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
|
|
|
|||
|
|
@ -1509,6 +1509,24 @@ This change is a breaking change. You should [create a runner in the UI](../ci/r
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Removal of tags from small SaaS runners on Linux
|
||||
|
||||
<div class="deprecation-notes">
|
||||
- Announced in GitLab <span class="milestone">16.9</span>
|
||||
- Removal in GitLab <span class="milestone">17.0</span> ([breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change))
|
||||
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/30829).
|
||||
</div>
|
||||
|
||||
Due to historical reasons, small Linux SaaS Runners had a lot of tags attached because they were used as labels. We want to streamline the tag to just use `saas-linux-small-amd64` and be consistent across all SaaS runners.
|
||||
|
||||
We are deprecating the tags: `docker`, `east-c`, `gce`, `git-annex`, `linux`, `mongo`, `mysql`, `postgres`, `ruby`, `shared`.
|
||||
|
||||
For more information, see [Removing tags from our small SaaS runner on Linux](https://about.gitlab.com/blog/2023/08/15/removing-tags-from-small-saas-runner-on-linux/).
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Rename the 'require_password_to_approve' field
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
@ -1849,6 +1867,25 @@ You can still access unified approval rules with the API.
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Upgrading the operating system version of GitLab SaaS runners on Linux
|
||||
|
||||
<div class="deprecation-notes">
|
||||
- Announced in GitLab <span class="milestone">16.9</span>
|
||||
- Removal in GitLab <span class="milestone">17.0</span> ([breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change))
|
||||
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/ci-cd/shared-runners/infrastructure/-/issues/60).
|
||||
</div>
|
||||
|
||||
GitLab is upgrading the container-optimized operating system (COS) of the ephemeral VMs used to execute jobs for SaaS runners on Linux.
|
||||
That COS upgrade includes a Docker Engine upgrade from Version 19.03.15 to Version 23.0.5, which introduces a known compatibility issue.
|
||||
|
||||
Docker-in-Docker prior to version 20.10 or Kaniko images older than v1.9.0, will be unable to detect the container runtime and fail.
|
||||
|
||||
For more information, see [Upgrading the operating system version of our SaaS runners on Linux](https://about.gitlab.com/blog/2023/10/04/updating-the-os-version-of-saas-runners-on-linux/).
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Vulnerability confidence field
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
|
|||
|
|
@ -76,13 +76,16 @@ GitLab uses these IDs to look up users.
|
|||
If the identity provider does not know the current values for these fields,
|
||||
that provider may create duplicate users, or fail to complete expected actions.
|
||||
|
||||
To change the identifier values to match:
|
||||
To change the identifier values to match, you can do one of the following:
|
||||
|
||||
1. Have users unlink and relink themselves, based on the
|
||||
- Have users unlink and relink themselves, based on the
|
||||
[SAML authentication failed: User has already been taken](troubleshooting.md#message-saml-authentication-failed-user-has-already-been-taken)
|
||||
section.
|
||||
1. Unlink all users simultaneously by removing all users from the SCIM app while provisioning is turned on.
|
||||
1. Use the [SAML API](../../../api/saml.md) or [SCIM API](../../../api/scim.md) to manually correct the `extern_uid` stored for users to match the SAML
|
||||
- Unlink all users simultaneously by removing all users from the SCIM app while provisioning is turned on.
|
||||
|
||||
WARNING:
|
||||
This resets all users' roles in the top level group and subgroups to the [configured default membership role](index.md#configure-gitlab).
|
||||
- Use the [SAML API](../../../api/saml.md) or [SCIM API](../../../api/scim.md) to manually correct the `extern_uid` stored for users to match the SAML
|
||||
`NameId` or SCIM `externalId`.
|
||||
|
||||
You must not:
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ module API
|
|||
optional :namespace_aggregation_schedule_lease_duration_in_seconds, type: Integer, desc: 'Maximum duration (in seconds) between refreshes of namespace statistics (Default: 300)'
|
||||
optional :project_jobs_api_rate_limit, type: Integer, desc: 'Maximum authenticated requests to /project/:id/jobs per minute'
|
||||
optional :security_txt_content, type: String, desc: 'Public security contact information made available at https://gitlab.example.com/.well-known/security.txt'
|
||||
optional :downstream_pipeline_trigger_limit_per_project_user_sha, type: Integer, desc: 'Maximum number of downstream pipelines triggered per project'
|
||||
|
||||
Gitlab::SSHPublicKey.supported_types.each do |type|
|
||||
optional :"#{type}_key_restriction",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ module API
|
|||
|
||||
namespace 'usage_data' do
|
||||
before do
|
||||
not_found! unless Feature.enabled?(:usage_data_api, type: :ops)
|
||||
forbidden!('Invalid CSRF token is provided') unless verified_request?
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ module Gitlab
|
|||
threshold: -> { application_settings.projects_api_rate_limit_unauthenticated }, interval: 10.minutes
|
||||
},
|
||||
downstream_pipeline_trigger: {
|
||||
threshold: -> { ::Ci::TriggerDownstreamPipelineService::DOWNSTREAM_PIPELINE_TRIGGER_LIMIT_PER_PROJECT_USER_SHA }, interval: 1.minute
|
||||
threshold: -> { application_settings.downstream_pipeline_trigger_limit_per_project_user_sha }, interval: 1.minute
|
||||
}
|
||||
}.freeze
|
||||
end
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ module Gitlab
|
|||
|
||||
# Initialize gon.features with any flags that should be
|
||||
# made globally available to the frontend
|
||||
push_frontend_feature_flag(:usage_data_api, type: :ops)
|
||||
push_frontend_feature_flag(:security_auto_fix)
|
||||
push_frontend_feature_flag(:source_editor_toolbar)
|
||||
push_frontend_feature_flag(:vscode_web_ide, current_user)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ namespace :tw do
|
|||
CodeOwnerRule.new('Product Planning', '@msedlakjakubowski'),
|
||||
CodeOwnerRule.new('Project Management', '@msedlakjakubowski'),
|
||||
CodeOwnerRule.new('Provision', '@fneill'),
|
||||
CodeOwnerRule.new('Purchase', '@fneill'),
|
||||
CodeOwnerRule.new('Redirect', 'Redirect'),
|
||||
# CodeOwnerRule.new('Respond', ''),
|
||||
CodeOwnerRule.new('Runner', '@fneill'),
|
||||
|
|
@ -77,6 +76,7 @@ namespace :tw do
|
|||
CodeOwnerRule.new('Solutions Architecture', '@jfullam @brianwald @Darwinjs'),
|
||||
CodeOwnerRule.new('Source Code', '@msedlakjakubowski'),
|
||||
CodeOwnerRule.new('Static Analysis', '@rdickenson'),
|
||||
# CodeOwnerRule.new('Subscription Management', ''),
|
||||
CodeOwnerRule.new('Tenant Scale', '@lciutacu'),
|
||||
CodeOwnerRule.new('Testing', '@eread'),
|
||||
CodeOwnerRule.new('Threat Insights', '@rdickenson'),
|
||||
|
|
|
|||
|
|
@ -3584,6 +3584,9 @@ msgstr ""
|
|||
msgid "AdminSettings|Limit the number of namespaces and projects that can be indexed."
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|Maximum downstream pipelines triggered in a project per user"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3743,6 +3746,9 @@ msgstr ""
|
|||
msgid "AdminSettings|The latest artifacts for all jobs in the most recent successful pipelines in each project are stored and do not expire."
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|The maximum number of downstream pipelines triggered in a project per user."
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|The maximum number of included files per pipeline."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -4289,10 +4295,10 @@ msgstr ""
|
|||
msgid "Admin|Deploy Keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin|Duo Pro"
|
||||
msgid "Admin|Geo"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin|Geo"
|
||||
msgid "Admin|GitLab Duo Pro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin|Kubernetes"
|
||||
|
|
@ -8096,13 +8102,13 @@ msgstr ""
|
|||
msgid "Billing|An error occurred while loading billable members list."
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|An error occurred while loading details for the Duo Pro add-on. If the problem persists, please %{supportLinkStart}contact support%{supportLinkEnd}."
|
||||
msgid "Billing|An error occurred while loading details for the GitLab Duo Pro add-on. If the problem persists, please %{supportLinkStart}contact support%{supportLinkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|An error occurred while loading pending members list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|An error occurred while loading users of the Duo Pro add-on. If the problem persists, please %{supportLinkStart}contact support%{supportLinkEnd}."
|
||||
msgid "Billing|An error occurred while loading users of the GitLab Duo Pro add-on. If the problem persists, please %{supportLinkStart}contact support%{supportLinkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|An error occurred while removing a billable member."
|
||||
|
|
@ -8120,10 +8126,10 @@ msgstr ""
|
|||
msgid "Billing|Enter at least three characters to search."
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|Error assigning Duo Pro add-on"
|
||||
msgid "Billing|Error assigning GitLab Duo Pro add-on"
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|Error un-assigning Duo Pro add-on"
|
||||
msgid "Billing|Error un-assigning GitLab Duo Pro add-on"
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|Explore paid plans"
|
||||
|
|
@ -8185,7 +8191,7 @@ msgstr ""
|
|||
msgid "Billing|You can upgrade to a paid tier to get access to more features."
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|You have assigned all available Duo Pro add-on seats. Please %{salesLinkStart}contact sales%{salesLinkEnd} if you would like to purchase more seats."
|
||||
msgid "Billing|You have assigned all available GitLab Duo Pro add-on seats. Please %{salesLinkStart}contact sales%{salesLinkEnd} if you would like to purchase more seats."
|
||||
msgstr ""
|
||||
|
||||
msgid "Billing|Your group recently changed to use the Free plan. %{over_limit_message} You can free up space for new members by removing those who no longer need access or toggling them to over-limit. To get an unlimited number of members, you can %{link_start}upgrade%{link_end} to a paid tier."
|
||||
|
|
@ -12106,7 +12112,7 @@ msgstr ""
|
|||
msgid "CodeSuggestions|%{link_start}What are code suggestions?%{link_end}"
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|A user can be assigned a Duo Pro seat only once each billable month."
|
||||
msgid "CodeSuggestions|A user can be assigned a GitLab Duo Pro seat only once each billable month."
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Boost productivity by using %{linkStart}Code Suggestions%{linkEnd} to write and understand code. Starting in February 2024, Code Suggestions will be part of %{duoLinkStart}GitLab Duo Pro%{duoLinkEnd}, available to Premium and Ultimate users for purchase now."
|
||||
|
|
@ -12115,28 +12121,28 @@ msgstr ""
|
|||
msgid "CodeSuggestions|Code Suggestions"
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Duo Pro"
|
||||
msgid "CodeSuggestions|Enhance your coding experience with intelligent recommendations. %{linkStart}GitLab Duo Pro%{linkEnd} offers features that use generative AI to suggest code."
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Duo Pro add-on"
|
||||
msgid "CodeSuggestions|GitLab Duo Pro"
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Duo Pro add-on status"
|
||||
msgid "CodeSuggestions|GitLab Duo Pro add-on"
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Duo Pro seats used"
|
||||
msgid "CodeSuggestions|GitLab Duo Pro add-on status"
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Enhance your coding experience with intelligent recommendations. %{linkStart}Duo Pro%{linkEnd} offers features that use generative AI to suggest code."
|
||||
msgid "CodeSuggestions|GitLab Duo Pro seats used"
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Introducing Duo Pro"
|
||||
msgid "CodeSuggestions|Introducing GitLab Duo Pro"
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Introducing the GitLab Duo Pro add-on"
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Manage seat assignments for Duo Pro across your instance."
|
||||
msgid "CodeSuggestions|Manage seat assignments for GitLab Duo Pro across your instance."
|
||||
msgstr ""
|
||||
|
||||
msgid "CodeSuggestions|Projects in this group can use Code Suggestions"
|
||||
|
|
@ -12210,9 +12216,6 @@ msgstr ""
|
|||
msgid "Collapse AI-generated summary"
|
||||
msgstr ""
|
||||
|
||||
msgid "Collapse all threads"
|
||||
msgstr ""
|
||||
|
||||
msgid "Collapse eligible approvers"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -20308,9 +20311,6 @@ msgstr ""
|
|||
msgid "Expand all files"
|
||||
msgstr ""
|
||||
|
||||
msgid "Expand all threads"
|
||||
msgstr ""
|
||||
|
||||
msgid "Expand eligible approvers"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -24601,6 +24601,9 @@ msgstr ""
|
|||
msgid "Hide Live Preview"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hide all comments"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hide archived projects"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -33496,6 +33499,12 @@ msgstr ""
|
|||
msgid "Notify|Remote mirror"
|
||||
msgstr ""
|
||||
|
||||
msgid "Notify|Review changes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Notify|Review requested"
|
||||
msgstr ""
|
||||
|
||||
msgid "Notify|SMTP host issue:"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -33589,6 +33598,9 @@ msgstr ""
|
|||
msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
|
||||
msgstr ""
|
||||
|
||||
msgid "Notify|You were added as a reviewer on %{long_mr} by %{name}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Notify|Your CSV import for project %{project_link} has been completed."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46546,6 +46558,9 @@ msgstr ""
|
|||
msgid "Show all breadcrumbs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show all comments"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show all epics"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -53336,9 +53351,6 @@ msgstr ""
|
|||
msgid "UsageQuota|Dependency proxy"
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|Duo Pro"
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|Filter charts by year"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -53348,6 +53360,9 @@ msgstr ""
|
|||
msgid "UsageQuota|Git repository."
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|GitLab Duo Pro"
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :member_approval, class: 'Members::MemberApproval' do
|
||||
requested_by { association(:user) }
|
||||
reviewed_by { association(:user) }
|
||||
old_access_level { ::Gitlab::Access::GUEST }
|
||||
new_access_level { ::Gitlab::Access::DEVELOPER }
|
||||
status { ::Members::MemberApproval.statuses[:pending] }
|
||||
member { association(:project_member) } # default
|
||||
member_namespace_id { member.member_namespace_id }
|
||||
|
||||
# Traits for specific group members
|
||||
trait :for_group_member do
|
||||
member { association(:group_member) }
|
||||
end
|
||||
|
||||
trait :for_project_member do
|
||||
member { association(:project_member) }
|
||||
end
|
||||
|
||||
trait(:guest) { old_access_level { GroupMember::GUEST } }
|
||||
trait(:reporter) { old_access_level { GroupMember::REPORTER } }
|
||||
trait(:developer) { old_access_level { GroupMember::DEVELOPER } }
|
||||
trait(:maintainer) { old_access_level { GroupMember::MAINTAINER } }
|
||||
trait(:owner) { old_access_level { GroupMember::OWNER } }
|
||||
|
||||
trait(:to_guest) { new_access_level { GroupMember::GUEST } }
|
||||
trait(:to_reporter) { new_access_level { GroupMember::REPORTER } }
|
||||
trait(:to_developer) { new_access_level { GroupMember::DEVELOPER } }
|
||||
trait(:to_maintainer) { new_access_level { GroupMember::MAINTAINER } }
|
||||
trait(:to_owner) { new_access_level { GroupMember::OWNER } }
|
||||
end
|
||||
end
|
||||
|
|
@ -459,6 +459,7 @@ RSpec.describe 'Admin updates settings', feature_category: :shared do
|
|||
uncheck 'Keep the latest artifacts for all jobs in the latest successful pipelines'
|
||||
uncheck 'Enable pipeline suggestion banner'
|
||||
fill_in 'application_setting_ci_max_includes', with: 200
|
||||
fill_in 'application_setting_downstream_pipeline_trigger_limit_per_project_user_sha', with: 500
|
||||
click_button 'Save changes'
|
||||
end
|
||||
|
||||
|
|
@ -467,6 +468,7 @@ RSpec.describe 'Admin updates settings', feature_category: :shared do
|
|||
expect(current_settings.keep_latest_artifact).to be false
|
||||
expect(current_settings.suggest_pipeline_enabled).to be false
|
||||
expect(current_settings.ci_max_includes).to be 200
|
||||
expect(current_settings.downstream_pipeline_trigger_limit_per_project_user_sha).to be 500
|
||||
expect(page).to have_content "Application settings saved successfully"
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ describe('DiffDiscussions', () => {
|
|||
let wrapper;
|
||||
const getDiscussionsMockData = () => [{ ...discussionsMockData }];
|
||||
|
||||
const createComponent = (props) => {
|
||||
const createComponent = (props, discussions = getDiscussionsMockData()) => {
|
||||
store = createStore();
|
||||
wrapper = mount(DiffDiscussions, {
|
||||
store,
|
||||
propsData: {
|
||||
discussions: getDiscussionsMockData(),
|
||||
discussions,
|
||||
...props,
|
||||
},
|
||||
});
|
||||
|
|
@ -43,7 +43,9 @@ describe('DiffDiscussions', () => {
|
|||
const findDiffNotesToggle = () => wrapper.find('.js-diff-notes-toggle');
|
||||
|
||||
it('renders collapsible discussion button', () => {
|
||||
createComponent({ shouldCollapseDiscussions: true });
|
||||
const discussions = getDiscussionsMockData();
|
||||
discussions[0].expandedOnDiff = true;
|
||||
createComponent({ shouldCollapseDiscussions: true }, discussions);
|
||||
const diffNotesToggle = findDiffNotesToggle();
|
||||
|
||||
expect(diffNotesToggle.exists()).toBe(true);
|
||||
|
|
@ -52,19 +54,19 @@ describe('DiffDiscussions', () => {
|
|||
});
|
||||
|
||||
it('dispatches toggleDiscussion when clicking collapse button', () => {
|
||||
createComponent({ shouldCollapseDiscussions: true });
|
||||
const discussions = getDiscussionsMockData();
|
||||
discussions[0].expandedOnDiff = true;
|
||||
createComponent({ shouldCollapseDiscussions: true }, discussions);
|
||||
jest.spyOn(store, 'dispatch').mockImplementation();
|
||||
|
||||
findDiffNotesToggle().trigger('click');
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith('toggleDiscussion', {
|
||||
discussionId: discussionsMockData.id,
|
||||
});
|
||||
expect(store.dispatch).toHaveBeenCalledWith('diffs/toggleFileDiscussion', discussions[0]);
|
||||
});
|
||||
|
||||
it('renders expand button when discussion is collapsed', () => {
|
||||
const discussions = getDiscussionsMockData();
|
||||
discussions[0].expanded = false;
|
||||
discussions[0].expandedOnDiff = false;
|
||||
createComponent({ discussions, shouldCollapseDiscussions: true });
|
||||
const diffNotesToggle = findDiffNotesToggle();
|
||||
|
||||
|
|
@ -76,7 +78,7 @@ describe('DiffDiscussions', () => {
|
|||
|
||||
it('hides discussion when collapsed', () => {
|
||||
const discussions = getDiscussionsMockData();
|
||||
discussions[0].expanded = false;
|
||||
discussions[0].expandedOnDiff = false;
|
||||
createComponent({ discussions, shouldCollapseDiscussions: true });
|
||||
|
||||
expect(findNoteableDiscussion().isVisible()).toBe(false);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ describe('DiffFileHeader component', () => {
|
|||
diffHasDiscussions: () => diffHasDiscussionsResultMock,
|
||||
},
|
||||
actions: {
|
||||
toggleFileDiscussions: jest.fn(),
|
||||
toggleFileDiscussionWrappers: jest.fn(),
|
||||
toggleFullDiff: jest.fn(),
|
||||
setCurrentFileHash: jest.fn(),
|
||||
|
|
|
|||
|
|
@ -1059,62 +1059,6 @@ describe('DiffsStoreActions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('toggleFileDiscussions', () => {
|
||||
it('should dispatch collapseDiscussion when all discussions are expanded', () => {
|
||||
const getters = {
|
||||
getDiffFileDiscussions: jest.fn(() => [{ id: 1 }]),
|
||||
diffHasAllExpandedDiscussions: jest.fn(() => true),
|
||||
diffHasAllCollapsedDiscussions: jest.fn(() => false),
|
||||
};
|
||||
|
||||
const dispatch = jest.fn();
|
||||
|
||||
diffActions.toggleFileDiscussions({ getters, dispatch });
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith(
|
||||
'collapseDiscussion',
|
||||
{ discussionId: 1 },
|
||||
{ root: true },
|
||||
);
|
||||
});
|
||||
|
||||
it('should dispatch expandDiscussion when all discussions are collapsed', () => {
|
||||
const getters = {
|
||||
getDiffFileDiscussions: jest.fn(() => [{ id: 1 }]),
|
||||
diffHasAllExpandedDiscussions: jest.fn(() => false),
|
||||
diffHasAllCollapsedDiscussions: jest.fn(() => true),
|
||||
};
|
||||
|
||||
const dispatch = jest.fn();
|
||||
|
||||
diffActions.toggleFileDiscussions({ getters, dispatch });
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith(
|
||||
'expandDiscussion',
|
||||
{ discussionId: 1 },
|
||||
{ root: true },
|
||||
);
|
||||
});
|
||||
|
||||
it('should dispatch expandDiscussion when some discussions are collapsed and others are expanded for the collapsed discussion', () => {
|
||||
const getters = {
|
||||
getDiffFileDiscussions: jest.fn(() => [{ expanded: false, id: 1 }]),
|
||||
diffHasAllExpandedDiscussions: jest.fn(() => false),
|
||||
diffHasAllCollapsedDiscussions: jest.fn(() => false),
|
||||
};
|
||||
|
||||
const dispatch = jest.fn();
|
||||
|
||||
diffActions.toggleFileDiscussions({ getters, dispatch });
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith(
|
||||
'expandDiscussion',
|
||||
{ discussionId: 1 },
|
||||
{ root: true },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('scrollToLineIfNeededInline', () => {
|
||||
const lineMock = {
|
||||
line_code: 'ABC_123',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
|
||||
import {
|
||||
PARALLEL_DIFF_VIEW_TYPE,
|
||||
INLINE_DIFF_VIEW_TYPE,
|
||||
INLINE_DIFF_LINES_KEY,
|
||||
} from '~/diffs/constants';
|
||||
import * as getters from '~/diffs/store/getters';
|
||||
import state from '~/diffs/store/modules/diff_state';
|
||||
import { getDiffFileMock } from 'jest/diffs/mock_data/diff_file';
|
||||
|
|
@ -527,4 +531,63 @@ describe('Diffs Module Getters', () => {
|
|||
expect(getters.pinnedFile({}, {})).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('allDiffDiscussionsExpanded', () => {
|
||||
it('returns true when all line discussions are expanded', () => {
|
||||
localState.diffFiles = [
|
||||
{
|
||||
[INLINE_DIFF_LINES_KEY]: [
|
||||
{ discussionsExpanded: true, discussions: [{}] },
|
||||
{ discussionsExpanded: true, discussions: [{}] },
|
||||
],
|
||||
},
|
||||
];
|
||||
expect(getters.allDiffDiscussionsExpanded(localState)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false if at least one line discussion is collapsed', () => {
|
||||
localState.diffFiles = [
|
||||
{
|
||||
[INLINE_DIFF_LINES_KEY]: [
|
||||
{ discussionsExpanded: true, discussions: [{}] },
|
||||
{ discussionsExpanded: false, discussions: [{}] },
|
||||
],
|
||||
},
|
||||
];
|
||||
expect(getters.allDiffDiscussionsExpanded(localState)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false if at least one image discussion is collapsed', () => {
|
||||
localState.diffFiles = [
|
||||
{
|
||||
[INLINE_DIFF_LINES_KEY]: [
|
||||
{ discussionsExpanded: true, discussions: [{}] },
|
||||
{ discussionsExpanded: true, discussions: [{}] },
|
||||
],
|
||||
},
|
||||
{
|
||||
[INLINE_DIFF_LINES_KEY]: [],
|
||||
viewer: { name: 'image' },
|
||||
discussions: [{ expandedOnDiff: false }],
|
||||
},
|
||||
];
|
||||
expect(getters.allDiffDiscussionsExpanded(localState)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true if all image discussions are expanded', () => {
|
||||
localState.diffFiles = [
|
||||
{
|
||||
viewer: { name: 'text' },
|
||||
[INLINE_DIFF_LINES_KEY]: [],
|
||||
discussions: [],
|
||||
},
|
||||
{
|
||||
viewer: { name: 'image' },
|
||||
[INLINE_DIFF_LINES_KEY]: [],
|
||||
discussions: [{ expandedOnDiff: true }, { expandedOnDiff: true }],
|
||||
},
|
||||
];
|
||||
expect(getters.allDiffDiscussionsExpanded(localState)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -674,6 +674,167 @@ describe('DiffsStoreMutations', () => {
|
|||
|
||||
expect(state.diffFiles[0].discussions.length).toEqual(1);
|
||||
});
|
||||
|
||||
describe('expanded state', () => {
|
||||
it('should expand discussion by default', () => {
|
||||
const diffPosition = {
|
||||
base_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
|
||||
head_sha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
|
||||
new_line: null,
|
||||
new_path: '500-lines-4.txt',
|
||||
old_line: 5,
|
||||
old_path: '500-lines-4.txt',
|
||||
start_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
|
||||
};
|
||||
|
||||
const state = {
|
||||
latestDiff: true,
|
||||
diffFiles: [
|
||||
{
|
||||
file_hash: 'ABC',
|
||||
[INLINE_DIFF_LINES_KEY]: [
|
||||
{
|
||||
line_code: 'ABC_1',
|
||||
discussions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const discussion = {
|
||||
id: 1,
|
||||
line_code: 'ABC_2',
|
||||
line_codes: ['ABC_1'],
|
||||
diff_discussion: true,
|
||||
resolvable: true,
|
||||
original_position: {},
|
||||
position: {},
|
||||
positions: [diffPosition],
|
||||
diff_file: {
|
||||
file_hash: state.diffFiles[0].file_hash,
|
||||
},
|
||||
};
|
||||
|
||||
const diffPositionByLineCode = {
|
||||
ABC_1: diffPosition,
|
||||
};
|
||||
|
||||
mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, {
|
||||
discussion,
|
||||
diffPositionByLineCode,
|
||||
});
|
||||
|
||||
expect(state.diffFiles[0][INLINE_DIFF_LINES_KEY][0].discussionsExpanded).toBe(true);
|
||||
});
|
||||
|
||||
it('should collapse resolved discussion', () => {
|
||||
const diffPosition = {
|
||||
base_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
|
||||
head_sha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
|
||||
new_line: null,
|
||||
new_path: '500-lines-4.txt',
|
||||
old_line: 5,
|
||||
old_path: '500-lines-4.txt',
|
||||
start_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
|
||||
};
|
||||
|
||||
const state = {
|
||||
latestDiff: true,
|
||||
diffFiles: [
|
||||
{
|
||||
file_hash: 'ABC',
|
||||
[INLINE_DIFF_LINES_KEY]: [
|
||||
{
|
||||
line_code: 'ABC_1',
|
||||
discussions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const discussion = {
|
||||
id: 1,
|
||||
line_code: 'ABC_2',
|
||||
line_codes: ['ABC_1'],
|
||||
diff_discussion: true,
|
||||
resolvable: true,
|
||||
original_position: {},
|
||||
position: {},
|
||||
positions: [diffPosition],
|
||||
diff_file: {
|
||||
file_hash: state.diffFiles[0].file_hash,
|
||||
},
|
||||
resolved: true,
|
||||
};
|
||||
|
||||
const diffPositionByLineCode = {
|
||||
ABC_1: diffPosition,
|
||||
};
|
||||
|
||||
mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, {
|
||||
discussion,
|
||||
diffPositionByLineCode,
|
||||
});
|
||||
|
||||
expect(state.diffFiles[0][INLINE_DIFF_LINES_KEY][0].discussionsExpanded).toBe(false);
|
||||
});
|
||||
|
||||
it('should keep resolved state for expanded discussion update', () => {
|
||||
const diffPosition = {
|
||||
base_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
|
||||
head_sha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
|
||||
new_line: null,
|
||||
new_path: '500-lines-4.txt',
|
||||
old_line: 5,
|
||||
old_path: '500-lines-4.txt',
|
||||
start_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
|
||||
};
|
||||
|
||||
const state = {
|
||||
latestDiff: true,
|
||||
diffFiles: [
|
||||
{
|
||||
file_hash: 'ABC',
|
||||
[INLINE_DIFF_LINES_KEY]: [
|
||||
{
|
||||
line_code: 'ABC_1',
|
||||
discussions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const discussion = {
|
||||
id: 1,
|
||||
line_code: 'ABC_2',
|
||||
line_codes: ['ABC_1'],
|
||||
diff_discussion: true,
|
||||
resolvable: true,
|
||||
original_position: {},
|
||||
position: {},
|
||||
positions: [diffPosition],
|
||||
diff_file: {
|
||||
file_hash: state.diffFiles[0].file_hash,
|
||||
},
|
||||
};
|
||||
|
||||
const diffPositionByLineCode = {
|
||||
ABC_1: diffPosition,
|
||||
};
|
||||
|
||||
mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, {
|
||||
discussion,
|
||||
diffPositionByLineCode,
|
||||
});
|
||||
|
||||
mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, {
|
||||
discussion: { ...discussion, resolved: true },
|
||||
diffPositionByLineCode,
|
||||
});
|
||||
|
||||
expect(state.diffFiles[0][INLINE_DIFF_LINES_KEY][0].discussionsExpanded).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('REMOVE_LINE_DISCUSSIONS', () => {
|
||||
|
|
@ -1121,6 +1282,61 @@ describe('DiffsStoreMutations', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('TOGGLE_FILE_DISCUSSION_EXPAND', () => {
|
||||
const fileHash = 'foo';
|
||||
|
||||
it('expands collapsed discussion', () => {
|
||||
const discussion = {
|
||||
diff_file: { file_hash: fileHash },
|
||||
expandedOnDiff: false,
|
||||
};
|
||||
const state = {
|
||||
diffFiles: [{ file_hash: fileHash, discussions: [discussion] }],
|
||||
};
|
||||
|
||||
mutations[types.TOGGLE_FILE_DISCUSSION_EXPAND](state, discussion);
|
||||
|
||||
expect(state.diffFiles[0].discussions[0].expandedOnDiff).toBe(true);
|
||||
});
|
||||
|
||||
it('collapses expanded discussion', () => {
|
||||
const discussion = {
|
||||
diff_file: { file_hash: fileHash },
|
||||
expandedOnDiff: true,
|
||||
};
|
||||
const state = {
|
||||
diffFiles: [{ file_hash: fileHash, discussions: [discussion] }],
|
||||
};
|
||||
|
||||
mutations[types.TOGGLE_FILE_DISCUSSION_EXPAND](state, discussion);
|
||||
|
||||
expect(state.diffFiles[0].discussions[0].expandedOnDiff).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SET_EXPAND_ALL_DIFF_DISCUSSIONS', () => {
|
||||
it('expands all discussions', () => {
|
||||
const state = {
|
||||
diffFiles: [
|
||||
{
|
||||
[INLINE_DIFF_LINES_KEY]: [
|
||||
{ line_code: 'foo', discussions: [{}], discussionsExpanded: false },
|
||||
],
|
||||
},
|
||||
{
|
||||
[INLINE_DIFF_LINES_KEY]: [],
|
||||
discussions: [{ expandedOnDiff: false }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.SET_EXPAND_ALL_DIFF_DISCUSSIONS](state, true);
|
||||
|
||||
expect(state.diffFiles[0][INLINE_DIFF_LINES_KEY][0].discussionsExpanded).toBe(true);
|
||||
expect(state.diffFiles[1].discussions[0].expandedOnDiff).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SET_PINNED_FILE_HASH', () => {
|
||||
it('set pinned file hash', () => {
|
||||
const state = {};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,13 @@ import MockAdapter from 'axios-mock-adapter';
|
|||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
import { createStore } from '~/mr_notes/stores';
|
||||
import { getDiffFileMock } from 'jest/diffs/mock_data/diff_file';
|
||||
import { SET_DIFF_DATA_BATCH, SET_LINE_DISCUSSIONS_FOR_FILE } from '~/diffs/store/mutation_types';
|
||||
import { discussionMock } from 'jest/notes/mock_data';
|
||||
import { getDiffPositionByLineCode } from '~/diffs/store/utils';
|
||||
import { INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
|
||||
import { ADD_OR_UPDATE_DISCUSSIONS } from '~/notes/stores/mutation_types';
|
||||
import mutationTypes from '~/mr_notes/stores/mutation_types';
|
||||
|
||||
describe('MR Notes Mutator Actions', () => {
|
||||
let store;
|
||||
|
|
@ -61,4 +68,44 @@ describe('MR Notes Mutator Actions', () => {
|
|||
expect(store.state.page.failedToLoadMetadata).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleAllVisibleDiscussions', () => {
|
||||
beforeEach(() => {
|
||||
const diff = getDiffFileMock();
|
||||
const discussion = {
|
||||
...discussionMock,
|
||||
diff_file: diff,
|
||||
line_code: diff[INLINE_DIFF_LINES_KEY][0].line_code,
|
||||
};
|
||||
store.commit(ADD_OR_UPDATE_DISCUSSIONS, [discussion]);
|
||||
store.commit(`diffs/${SET_DIFF_DATA_BATCH}`, { diff_files: [diff] });
|
||||
store.commit(`diffs/${SET_LINE_DISCUSSIONS_FOR_FILE}`, {
|
||||
discussion,
|
||||
diffPositionByLineCode: getDiffPositionByLineCode(store.state.diffs.diffFiles),
|
||||
hash: diff.file_hash,
|
||||
});
|
||||
});
|
||||
|
||||
it('dispatches toggleAllDiscussions', async () => {
|
||||
expect(store.state.notes.discussions[0].expanded).toEqual(true);
|
||||
|
||||
await store.dispatch('toggleAllVisibleDiscussions');
|
||||
|
||||
expect(store.state.notes.discussions[0].expanded).toEqual(false);
|
||||
});
|
||||
|
||||
it('dispatches toggleAllDiffDiscussions when on diffs page', async () => {
|
||||
store.commit(mutationTypes.SET_ACTIVE_TAB, 'diffs');
|
||||
|
||||
expect(store.state.diffs.diffFiles[0][INLINE_DIFF_LINES_KEY][0].discussionsExpanded).toEqual(
|
||||
true,
|
||||
);
|
||||
|
||||
await store.dispatch('toggleAllVisibleDiscussions');
|
||||
|
||||
expect(store.state.diffs.diffFiles[0][INLINE_DIFF_LINES_KEY][0].discussionsExpanded).toEqual(
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,37 +1,22 @@
|
|||
import { GlDisclosureDropdown, GlDisclosureDropdownItem } from '@gitlab/ui';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import Vue from 'vue';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import Vuex from 'vuex';
|
||||
import DiscussionCounter from '~/notes/components/discussion_counter.vue';
|
||||
import notesModule from '~/notes/stores/modules';
|
||||
import * as types from '~/notes/stores/mutation_types';
|
||||
import { discussionMock, noteableDataMock, notesDataMock, userDataMock } from '../mock_data';
|
||||
import { createStore } from '~/mr_notes/stores';
|
||||
import { discussionMock, noteableDataMock, notesDataMock } from '../mock_data';
|
||||
|
||||
describe('DiscussionCounter component', () => {
|
||||
let store;
|
||||
let wrapper;
|
||||
let setExpandDiscussionsFn;
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
beforeEach(() => {
|
||||
window.mrTabs = {};
|
||||
const { state, getters, mutations, actions } = notesModule();
|
||||
setExpandDiscussionsFn = jest.fn().mockImplementation(actions.setExpandDiscussions);
|
||||
|
||||
store = new Vuex.Store({
|
||||
state: {
|
||||
...state,
|
||||
userData: userDataMock,
|
||||
},
|
||||
getters,
|
||||
mutations,
|
||||
actions: {
|
||||
...actions,
|
||||
setExpandDiscussions: setExpandDiscussionsFn,
|
||||
},
|
||||
});
|
||||
store = createStore();
|
||||
store.dispatch('setNoteableData', {
|
||||
...noteableDataMock,
|
||||
create_issue_to_resolve_discussions_path: '/test',
|
||||
|
|
@ -39,10 +24,6 @@ describe('DiscussionCounter component', () => {
|
|||
store.dispatch('setNotesData', notesDataMock);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.vm.$destroy();
|
||||
});
|
||||
|
||||
describe('has no discussions', () => {
|
||||
it('does not render', () => {
|
||||
wrapper = mount(DiscussionCounter, { store, propsData: { blocksMerge: true } });
|
||||
|
|
@ -88,7 +69,7 @@ describe('DiscussionCounter component', () => {
|
|||
'changes background color to $color if blocksMerge is $blocksMerge',
|
||||
({ blocksMerge, color }) => {
|
||||
updateStore();
|
||||
store.state.unresolvedDiscussionsCount = 1;
|
||||
store.state.notes.unresolvedDiscussionsCount = 1;
|
||||
wrapper = mount(DiscussionCounter, { store, propsData: { blocksMerge } });
|
||||
|
||||
expect(wrapper.find('[data-testid="discussions-counter-text"]').classes()).toContain(color);
|
||||
|
|
@ -125,8 +106,10 @@ describe('DiscussionCounter component', () => {
|
|||
|
||||
describe('toggle all threads button', () => {
|
||||
let toggleAllButton;
|
||||
let discussion;
|
||||
|
||||
const updateStoreWithExpanded = async (expanded) => {
|
||||
const discussion = { ...discussionMock, expanded };
|
||||
discussion = { ...discussionMock, expanded };
|
||||
store.commit(types.ADD_OR_UPDATE_DISCUSSIONS, [discussion]);
|
||||
store.dispatch('updateResolvableDiscussionsCounts');
|
||||
wrapper = mount(DiscussionCounter, { store, propsData: { blocksMerge: true } });
|
||||
|
|
@ -134,34 +117,25 @@ describe('DiscussionCounter component', () => {
|
|||
toggleAllButton = wrapper.find('[data-testid="toggle-all-discussions-btn"]');
|
||||
};
|
||||
|
||||
it('calls button handler when clicked', async () => {
|
||||
await updateStoreWithExpanded(true);
|
||||
|
||||
toggleAllButton.trigger('click');
|
||||
|
||||
expect(setExpandDiscussionsFn).toHaveBeenCalledTimes(1);
|
||||
afterEach(() => {
|
||||
toggleAllButton = undefined;
|
||||
discussion = undefined;
|
||||
});
|
||||
|
||||
it('collapses all discussions if expanded', async () => {
|
||||
await updateStoreWithExpanded(true);
|
||||
|
||||
expect(wrapper.vm.allExpanded).toBe(true);
|
||||
|
||||
toggleAllButton.trigger('click');
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.vm.allExpanded).toBe(false);
|
||||
expect(store.state.notes.discussions[0].expanded).toBe(false);
|
||||
});
|
||||
|
||||
it('expands all discussions if collapsed', async () => {
|
||||
await updateStoreWithExpanded(false);
|
||||
|
||||
expect(wrapper.vm.allExpanded).toBe(false);
|
||||
|
||||
toggleAllButton.trigger('click');
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.vm.allExpanded).toBe(true);
|
||||
expect(store.state.notes.discussions[0].expanded).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1449,4 +1449,16 @@ describe('Actions Notes Store', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleAllDiscussions', () => {
|
||||
it('commits SET_EXPAND_ALL_DISCUSSIONS', () => {
|
||||
return testAction(
|
||||
actions.toggleAllDiscussions,
|
||||
undefined,
|
||||
{ allDiscussionsExpanded: false },
|
||||
[{ type: mutationTypes.SET_EXPAND_ALL_DISCUSSIONS, payload: true }],
|
||||
[],
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -578,4 +578,20 @@ describe('Getters Notes Store', () => {
|
|||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('allDiscussionsExpanded', () => {
|
||||
it('returns true when every discussion is expanded', () => {
|
||||
state = {
|
||||
discussions: [{ expanded: true }, { expanded: true }],
|
||||
};
|
||||
expect(getters.allDiscussionsExpanded(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when at least one discussion is collapsed', () => {
|
||||
state = {
|
||||
discussions: [{ expanded: true }, { expanded: false }],
|
||||
};
|
||||
expect(getters.allDiscussionsExpanded(state)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -940,4 +940,16 @@ describe('Notes Store mutations', () => {
|
|||
expect(state.doneFetchingBatchDiscussions).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SET_EXPAND_ALL_DISCUSSIONS', () => {
|
||||
it('should set expanded for every discussion', () => {
|
||||
const state = {
|
||||
discussions: [{ expanded: false }, { expanded: false }],
|
||||
};
|
||||
|
||||
mutations.SET_EXPAND_ALL_DISCUSSIONS(state, true);
|
||||
|
||||
expect(state.discussions).toStrictEqual([{ expanded: true }, { expanded: true }]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -85,17 +85,6 @@ RSpec.describe Resolvers::Ci::Catalog::ResourcesResolver, feature_category: :pip
|
|||
end
|
||||
end
|
||||
|
||||
context 'and the ci_guard_for_catalog_resource_scope FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_guard_for_catalog_resource_scope: false)
|
||||
end
|
||||
|
||||
it 'returns all the catalog resources' do
|
||||
expect(result.items.count).to be(3)
|
||||
expect(result.items.pluck(:name)).to contain_exactly('public', 'internal', 'z private test')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the scope is invalid' do
|
||||
let(:scope) { 'INVALID' }
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ RSpec.describe ApplicationSettingsHelper do
|
|||
project_download_export_limit project_export_limit project_import_limit
|
||||
raw_blob_request_limit group_export_limit group_download_export_limit
|
||||
group_import_limit users_get_by_id_limit search_rate_limit search_rate_limit_unauthenticated
|
||||
members_delete_limit
|
||||
members_delete_limit downstream_pipeline_trigger_limit_per_project_user_sha
|
||||
])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do
|
|||
it { expect(setting.bulk_import_concurrent_pipeline_batch_limit).to eq(25) }
|
||||
it { expect(setting.allow_project_creation_for_guest_and_below).to eq(true) }
|
||||
it { expect(setting.members_delete_limit).to eq(60) }
|
||||
it { expect(setting.downstream_pipeline_trigger_limit_per_project_user_sha).to eq(0) }
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
|
|
@ -244,6 +245,7 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do
|
|||
sidekiq_job_limiter_limit_bytes
|
||||
terminal_max_session_time
|
||||
users_get_by_id_limit
|
||||
downstream_pipeline_trigger_limit_per_project_user_sha
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -74,23 +74,9 @@ RSpec.describe Ci::Catalog::Listing, feature_category: :pipeline_composition do
|
|||
|
||||
let(:params) { { scope: :namespaces } }
|
||||
|
||||
context 'when the `ci_guard_query_for_catalog_resource_scope` ff is enabled' do
|
||||
it "returns the catalog resources belonging to the user's authorized namespaces" do
|
||||
is_expected.to contain_exactly(public_resource_a, public_resource_b, internal_resource,
|
||||
private_namespace_resource)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the `ci_guard_query_for_catalog_resource_scope` ff is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_guard_for_catalog_resource_scope: false)
|
||||
end
|
||||
|
||||
it 'returns all resources visible to the current user' do
|
||||
is_expected.to contain_exactly(
|
||||
public_resource_a, public_resource_b, private_namespace_resource,
|
||||
internal_resource)
|
||||
end
|
||||
it "returns the catalog resources belonging to the user's authorized namespaces" do
|
||||
is_expected.to contain_exactly(public_resource_a, public_resource_b, internal_resource,
|
||||
private_namespace_resource)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue