Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-08 06:08:19 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-08 06:08:19 +0300
commitbf293d47937b3332462689c3fecc868706553f3a (patch)
tree47f0f1063aa27e4529c23068537ce45d6adb4cf0
parent356e3c444dc8fab920d3547461b6ae721c5eb50f (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new Git repository type.md1
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new blob type.md1
-rw-r--r--app/assets/javascripts/analytics/shared/constants.js12
-rw-r--r--app/assets/javascripts/diffs/components/app.vue85
-rw-r--r--app/assets/javascripts/diffs/index.js32
-rw-r--r--app/assets/javascripts/lib/utils/constants.js2
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js2
-rw-r--r--app/assets/javascripts/mr_notes/init.js29
-rw-r--r--app/assets/javascripts/mr_notes/init_mr_notes.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/details.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/harbor_registry/constants/details.js2
-rw-r--r--app/assets/javascripts/super_sidebar/components/help_center.vue6
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss8
-rw-r--r--app/models/personal_access_token.rb9
-rw-r--r--app/services/personal_access_tokens/create_service.rb20
-rw-r--r--app/services/resource_access_tokens/create_service.rb6
-rw-r--r--config/feature_flags/development/adherence_report_ui.yml8
-rwxr-xr-xconfig/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20230527152402_p_ci_templates_pages_zola_monthly.yml24
-rwxr-xr-xconfig/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20230527152358_p_ci_templates_pages_zola_weekly.yml24
-rw-r--r--db/fixtures/development/25_api_personal_access_token.rb1
-rw-r--r--db/post_migrate/20230522073230_add_not_null_constraint_to_personal_access_tokens_expires_at.rb13
-rw-r--r--db/schema_migrations/202305220732301
-rw-r--r--db/structure.sql3
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/ci/jobs/index.md2
-rw-r--r--doc/development/cicd/cicd_tables.md8
-rw-r--r--doc/development/documentation/styleguide/index.md23
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md14
-rw-r--r--lib/api/resource_access_tokens.rb35
-rw-r--r--lib/gitlab/ci/templates/Flutter.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Pages/Zola.gitlab-ci.yml30
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb6
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml2
-rw-r--r--locale/gitlab.pot11
-rw-r--r--qa/qa/fixtures/package_managers/npm/npm_install_package_group.yaml.erb21
-rw-r--r--qa/qa/fixtures/package_managers/npm/npm_upload_package_group.yaml.erb14
-rw-r--r--qa/qa/fixtures/package_managers/npm/package.json.erb (renamed from qa/qa/fixtures/package_managers/npm/package_instance.json.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/npm/package_project.json.erb8
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_group_level_spec.rb175
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb2
-rw-r--r--spec/factories/personal_access_tokens.rb2
-rw-r--r--spec/frontend/diffs/components/app_spec.js109
-rw-r--r--spec/frontend/lib/utils/number_utility_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js2
-rw-r--r--spec/frontend/super_sidebar/components/help_center_spec.js17
-rw-r--r--spec/frontend_integration/diffs/diffs_interopability_spec.js29
-rw-r--r--spec/lib/api/entities/personal_access_token_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Pages/zola_gitlab_ci_yaml_spec.rb25
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb13
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb2
-rw-r--r--spec/models/personal_access_token_spec.rb30
-rw-r--r--spec/requests/api/internal/base_spec.rb3
-rw-r--r--spec/serializers/access_token_entity_base_spec.rb2
-rw-r--r--spec/services/personal_access_tokens/create_service_spec.rb7
61 files changed, 614 insertions, 299 deletions
diff --git a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
index e93c5d79964..88c82688273 100644
--- a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
@@ -542,7 +542,6 @@ That's all of the required database changes.
belongs_to :cool_widget, inverse_of: :cool_widget_state
- validates :verification_failure, length: { maximum: 255 }
validates :verification_state, :cool_widget, presence: true
end
end
diff --git a/.gitlab/issue_templates/Geo Replicate a new blob type.md b/.gitlab/issue_templates/Geo Replicate a new blob type.md
index 2183ba9c384..edef88cb022 100644
--- a/.gitlab/issue_templates/Geo Replicate a new blob type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new blob type.md
@@ -509,7 +509,6 @@ That's all of the required database changes.
belongs_to :cool_widget, inverse_of: :cool_widget_state
- validates :verification_failure, length: { maximum: 255 }
validates :verification_state, :cool_widget, presence: true
end
end
diff --git a/app/assets/javascripts/analytics/shared/constants.js b/app/assets/javascripts/analytics/shared/constants.js
index 9463286e53e..25699c17b10 100644
--- a/app/assets/javascripts/analytics/shared/constants.js
+++ b/app/assets/javascripts/analytics/shared/constants.js
@@ -133,15 +133,15 @@ export const METRIC_TOOLTIPS = {
},
[VULNERABILITY_METRICS.CRITICAL]: {
description: s__('ValueStreamAnalytics|Critical vulnerabilities over time.'),
- groupLink: '-/security/vulnerabilities',
- projectLink: '-/security/vulnerability_report',
- docsLink: helpPagePath('user/application_security/vulnerability_report/index'),
+ groupLink: '-/security/vulnerabilities?severity=CRITICAL',
+ projectLink: '-/security/vulnerability_report?severity=CRITICAL',
+ docsLink: helpPagePath('user/application_security/vulnerabilities/severities.html'),
},
[VULNERABILITY_METRICS.HIGH]: {
description: s__('ValueStreamAnalytics|High vulnerabilities over time.'),
- groupLink: '-/security/vulnerabilities',
- projectLink: '-/security/vulnerability_report',
- docsLink: helpPagePath('user/application_security/vulnerability_report/index'),
+ groupLink: '-/security/vulnerabilities?severity=HIGH',
+ projectLink: '-/security/vulnerability_report?severity=HIGH',
+ docsLink: helpPagePath('user/application_security/vulnerabilities/severities.html'),
},
[MERGE_REQUEST_METRICS.THROUGHPUT]: {
description: s__('ValueStreamAnalytics|The number of merge requests merged by month.'),
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index f644c69f0a0..c0a9643e59e 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -90,22 +90,6 @@ export default {
ALERT_COLLAPSED_FILES,
},
props: {
- endpoint: {
- type: String,
- required: true,
- },
- endpointMetadata: {
- type: String,
- required: true,
- },
- endpointBatch: {
- type: String,
- required: true,
- },
- endpointDiffForPath: {
- type: String,
- required: true,
- },
endpointCoverage: {
type: String,
required: false,
@@ -116,15 +100,6 @@ export default {
required: false,
default: '',
},
- endpointUpdateUser: {
- type: String,
- required: false,
- default: '',
- },
- projectPath: {
- type: String,
- required: true,
- },
shouldShow: {
type: Boolean,
required: false,
@@ -144,51 +119,6 @@ export default {
required: false,
default: '',
},
- isFluidLayout: {
- type: Boolean,
- required: false,
- default: false,
- },
- dismissEndpoint: {
- type: String,
- required: false,
- default: '',
- },
- showSuggestPopover: {
- type: Boolean,
- required: false,
- default: false,
- },
- fileByFileUserPreference: {
- type: Boolean,
- required: false,
- default: false,
- },
- defaultSuggestionCommitMessage: {
- type: String,
- required: false,
- default: '',
- },
- rehydratedMrReviews: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- sourceProjectDefaultUrl: {
- type: String,
- required: false,
- default: '',
- },
- sourceProjectFullPath: {
- type: String,
- required: false,
- default: '',
- },
- isForked: {
- type: Boolean,
- required: false,
- default: false,
- },
},
data() {
const treeWidth =
@@ -343,21 +273,6 @@ export default {
renderFileTree: 'adjustView',
},
mounted() {
- this.setBaseConfig({
- endpoint: this.endpoint,
- endpointMetadata: this.endpointMetadata,
- endpointBatch: this.endpointBatch,
- endpointDiffForPath: this.endpointDiffForPath,
- endpointCoverage: this.endpointCoverage,
- endpointUpdateUser: this.endpointUpdateUser,
- projectPath: this.projectPath,
- dismissEndpoint: this.dismissEndpoint,
- showSuggestPopover: this.showSuggestPopover,
- viewDiffsFileByFile: this.fileByFileUserPreference || false,
- defaultSuggestionCommitMessage: this.defaultSuggestionCommitMessage,
- mrReviews: this.rehydratedMrReviews,
- });
-
if (this.endpointCodequality) {
this.setCodequalityEndpoint(this.endpointCodequality);
}
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index 53c27632c4f..29cf90dcbe2 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -9,8 +9,6 @@ import eventHub from '../notes/event_hub';
import DiffsApp from './components/app.vue';
import { TREE_LIST_STORAGE_KEY, DIFF_WHITESPACE_COOKIE_NAME } from './constants';
-import { getReviewsForMergeRequest } from './utils/file_reviews';
-import { getDerivedMergeRequestInformation } from './utils/merge_request';
export default function initDiffsApp(store = notesStore) {
const el = document.getElementById('js-diffs-app');
@@ -32,26 +30,13 @@ export default function initDiffsApp(store = notesStore) {
},
data() {
return {
- endpoint: dataset.endpoint,
- endpointMetadata: dataset.endpointMetadata || '',
- endpointBatch: dataset.endpointBatch || '',
- endpointDiffForPath: dataset.endpointDiffForPath || '',
endpointCoverage: dataset.endpointCoverage || '',
endpointCodequality: dataset.endpointCodequality || '',
- endpointUpdateUser: dataset.updateCurrentUserPath,
- projectPath: dataset.projectPath,
helpPagePath: dataset.helpPagePath,
currentUser: JSON.parse(dataset.currentUserData) || {},
changesEmptyStateIllustration: dataset.changesEmptyStateIllustration,
- isFluidLayout: parseBoolean(dataset.isFluidLayout),
dismissEndpoint: dataset.dismissEndpoint,
- showSuggestPopover: parseBoolean(dataset.showSuggestPopover),
showWhitespaceDefault: parseBoolean(dataset.showWhitespaceDefault),
- viewDiffsFileByFile: parseBoolean(dataset.fileByFileDefault),
- defaultSuggestionCommitMessage: dataset.defaultSuggestionCommitMessage,
- sourceProjectDefaultUrl: dataset.sourceProjectDefaultUrl,
- sourceProjectFullPath: dataset.sourceProjectFullPath,
- isForked: parseBoolean(dataset.isForked),
};
},
computed: {
@@ -90,31 +75,14 @@ export default function initDiffsApp(store = notesStore) {
...mapActions('diffs', ['setRenderTreeList', 'setShowWhitespace']),
},
render(createElement) {
- const { mrPath } = getDerivedMergeRequestInformation({ endpoint: this.endpoint });
-
return createElement('diffs-app', {
props: {
- endpoint: this.endpoint,
- endpointMetadata: this.endpointMetadata,
- endpointBatch: this.endpointBatch,
- endpointDiffForPath: this.endpointDiffForPath,
endpointCoverage: this.endpointCoverage,
endpointCodequality: this.endpointCodequality,
- endpointUpdateUser: this.endpointUpdateUser,
currentUser: this.currentUser,
- projectPath: this.projectPath,
helpPagePath: this.helpPagePath,
shouldShow: this.activeTab === 'diffs',
changesEmptyStateIllustration: this.changesEmptyStateIllustration,
- isFluidLayout: this.isFluidLayout,
- dismissEndpoint: this.dismissEndpoint,
- showSuggestPopover: this.showSuggestPopover,
- fileByFileUserPreference: this.viewDiffsFileByFile,
- defaultSuggestionCommitMessage: this.defaultSuggestionCommitMessage,
- rehydratedMrReviews: getReviewsForMergeRequest(mrPath),
- sourceProjectDefaultUrl: this.sourceProjectDefaultUrl,
- sourceProjectFullPath: this.sourceProjectFullPath,
- isForked: this.isForked,
},
});
},
diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js
index fb69a61880a..d1e5e4eea13 100644
--- a/app/assets/javascripts/lib/utils/constants.js
+++ b/app/assets/javascripts/lib/utils/constants.js
@@ -27,7 +27,7 @@ export const DRAWER_Z_INDEX = 252;
export const MIN_USERNAME_LENGTH = 2;
-export const BYTES_FORMAT_BYTES = 'Bytes';
+export const BYTES_FORMAT_BYTES = 'B';
export const BYTES_FORMAT_KIB = 'KiB';
export const BYTES_FORMAT_MIB = 'MiB';
export const BYTES_FORMAT_GIB = 'GiB';
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index d64f84d2040..0e943cdb623 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -106,7 +106,7 @@ export function numberToHumanSize(size, digits = 2) {
switch (format) {
case BYTES_FORMAT_BYTES:
- return sprintf(__('%{size} bytes'), { size: humanSize });
+ return sprintf(__('%{size} B'), { size: humanSize });
case BYTES_FORMAT_KIB:
return sprintf(__('%{size} KiB'), { size: humanSize });
case BYTES_FORMAT_MIB:
diff --git a/app/assets/javascripts/mr_notes/init.js b/app/assets/javascripts/mr_notes/init.js
index 9852efea95f..e8e3376cee2 100644
--- a/app/assets/javascripts/mr_notes/init.js
+++ b/app/assets/javascripts/mr_notes/init.js
@@ -1,12 +1,14 @@
import { parseBoolean } from '~/lib/utils/common_utils';
-import store from '~/mr_notes/stores';
+import mrNotes from '~/mr_notes/stores';
import { getLocationHash } from '~/lib/utils/url_utility';
import eventHub from '~/notes/event_hub';
import { initReviewBar } from '~/batch_comments';
import { initDiscussionCounter } from '~/mr_notes/discussion_counter';
import { initOverviewTabCounter } from '~/mr_notes/init_count';
+import { getDerivedMergeRequestInformation } from '~/diffs/utils/merge_request';
+import { getReviewsForMergeRequest } from '~/diffs/utils/file_reviews';
-function setupMrNotesState(notesDataset) {
+function setupMrNotesState(store, notesDataset, diffsDataset) {
const noteableData = JSON.parse(notesDataset.noteableData);
noteableData.noteableType = notesDataset.noteableType;
noteableData.targetType = notesDataset.targetType;
@@ -15,26 +17,43 @@ function setupMrNotesState(notesDataset) {
const currentUserData = JSON.parse(notesDataset.currentUserData);
const endpoints = { metadata: notesDataset.endpointMetadata };
+ const { mrPath } = getDerivedMergeRequestInformation({ endpoint: diffsDataset.endpoint });
+
store.dispatch('setNotesData', notesData);
store.dispatch('setNoteableData', noteableData);
store.dispatch('setUserData', currentUserData);
store.dispatch('setTargetNoteHash', getLocationHash());
store.dispatch('setEndpoints', endpoints);
+ store.dispatch('diffs/setBaseConfig', {
+ endpoint: diffsDataset.endpoint,
+ endpointMetadata: diffsDataset.endpointMetadata,
+ endpointBatch: diffsDataset.endpointBatch,
+ endpointDiffForPath: diffsDataset.endpointDiffForPath,
+ endpointCoverage: diffsDataset.endpointCoverage,
+ endpointUpdateUser: diffsDataset.updateCurrentUserPath,
+ projectPath: diffsDataset.projectPath,
+ dismissEndpoint: diffsDataset.dismissEndpoint,
+ showSuggestPopover: parseBoolean(diffsDataset.showSuggestPopover),
+ viewDiffsFileByFile: parseBoolean(diffsDataset.fileByFileDefault),
+ defaultSuggestionCommitMessage: diffsDataset.defaultSuggestionCommitMessage,
+ mrReviews: getReviewsForMergeRequest(mrPath),
+ });
}
-export function initMrStateLazyLoad({ reviewBarParams } = {}) {
+export function initMrStateLazyLoad(store = mrNotes, { reviewBarParams } = {}) {
store.dispatch('setActiveTab', window.mrTabs.getCurrentAction());
window.mrTabs.eventHub.$on('MergeRequestTabChange', (value) =>
store.dispatch('setActiveTab', value),
);
const discussionsEl = document.getElementById('js-vue-mr-discussions');
- const notesDataset = discussionsEl.dataset;
+ const diffsEl = document.getElementById('js-diffs-app');
+
let stop = () => {};
stop = store.watch(
(state) => state.page.activeTab,
(activeTab) => {
- setupMrNotesState(notesDataset);
+ setupMrNotesState(store, discussionsEl.dataset, diffsEl.dataset);
// prevent loading MR state on commits and pipelines pages
// this is due to them having a shared controller with the Overview page
diff --git a/app/assets/javascripts/mr_notes/init_mr_notes.js b/app/assets/javascripts/mr_notes/init_mr_notes.js
index e0a8d1f7e7d..3fcf0958868 100644
--- a/app/assets/javascripts/mr_notes/init_mr_notes.js
+++ b/app/assets/javascripts/mr_notes/init_mr_notes.js
@@ -13,7 +13,7 @@ export default function initMrNotes(lazyLoadParams) {
action: mrShowNode.dataset.mrAction,
});
- initMrStateLazyLoad(lazyLoadParams);
+ initMrStateLazyLoad(undefined, lazyLoadParams);
document.addEventListener('merged:UpdateActions', () => {
initRevertCommitModal('i_code_review_post_merge_submit_revert_modal');
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/details.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/details.js
index 7ac803a8ece..3a5992d182a 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/details.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/details.js
@@ -68,7 +68,7 @@ export const MISSING_MANIFEST_WARNING_TOOLTIP = s__(
export const CREATED_AT = s__('ContainerRegistry|Created %{time}');
export const NOT_AVAILABLE_TEXT = __('Not applicable.');
-export const NOT_AVAILABLE_SIZE = __('0 bytes');
+export const NOT_AVAILABLE_SIZE = __('0 B');
export const CLEANUP_UNSCHEDULED_TEXT = s__('ContainerRegistry|Cleanup will run %{time}');
export const CLEANUP_SCHEDULED_TEXT = s__('ContainerRegistry|Cleanup pending');
diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/constants/details.js b/app/assets/javascripts/packages_and_registries/harbor_registry/constants/details.js
index 5b4b85ec31e..ce98be914ae 100644
--- a/app/assets/javascripts/packages_and_registries/harbor_registry/constants/details.js
+++ b/app/assets/javascripts/packages_and_registries/harbor_registry/constants/details.js
@@ -16,7 +16,7 @@ export const DIGEST_LABEL = s__('HarborRegistry|Digest: %{imageId}');
export const CREATED_AT_LABEL = s__('HarborRegistry|Published %{timeInfo}');
export const NOT_AVAILABLE_TEXT = __('Not applicable.');
-export const NOT_AVAILABLE_SIZE = __('0 bytes');
+export const NOT_AVAILABLE_SIZE = __('0 B');
export const TOKEN_TYPE_TAG_NAME = 'tag_name';
diff --git a/app/assets/javascripts/super_sidebar/components/help_center.vue b/app/assets/javascripts/super_sidebar/components/help_center.vue
index 1a965f21ef5..6d51063dbfb 100644
--- a/app/assets/javascripts/super_sidebar/components/help_center.vue
+++ b/app/assets/javascripts/super_sidebar/components/help_center.vue
@@ -216,7 +216,11 @@ export default {
>
<template #toggle>
<gl-button category="tertiary" icon="question-o" class="btn-with-notification">
- <span v-if="showWhatsNewNotification" class="notification-dot-info"></span>
+ <span
+ v-if="showWhatsNewNotification"
+ data-testid="notification-dot"
+ class="notification-dot-info"
+ ></span>
{{ $options.i18n.help }}
</gl-button>
</template>
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 7a3db63b478..b7a674a35e7 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -489,14 +489,12 @@
padding: 0;
.issuable-context-form {
- $issue-sticky-header-height: 76px;
-
- top: calc(#{$calc-application-header-height} + #{$issue-sticky-header-height});
- height: calc(#{$calc-application-viewport-height} - #{$issue-sticky-header-height} - var(--mr-review-bar-height) - $content-wrapper-padding);
+ top: calc(#{$calc-application-header-height} + #{$mr-sticky-header-height});
+ height: calc(#{$calc-application-viewport-height} - #{$mr-sticky-header-height} - var(--mr-review-bar-height));
position: sticky;
overflow: auto;
padding: 0 15px;
- margin-bottom: calc((#{$header-height} + $issue-sticky-header-height) * -1);
+ margin-bottom: calc((#{$content-wrapper-padding} * -1) + var(--mr-review-bar-height));
}
}
}
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index 80825c4bf08..2749404b7b5 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -44,6 +44,7 @@ class PersonalAccessToken < ApplicationRecord
validates :scopes, presence: true
validate :validate_scopes
+ validates :expires_at, presence: true, on: :create
validate :expires_at_before_instance_max_expiry_date, on: :create
def revoke!
@@ -54,14 +55,6 @@ class PersonalAccessToken < ApplicationRecord
!revoked? && !expired?
end
- # fall back to default value until background migration has updated all
- # existing PATs and we can add a validation
- # https://gitlab.com/gitlab-org/gitlab/-/issues/369123
- def expires_at=(value)
- datetime = value.presence || MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS.days.from_now
- super(datetime)
- end
-
override :simple_sorts
def self.simple_sorts
super.merge(
diff --git a/app/services/personal_access_tokens/create_service.rb b/app/services/personal_access_tokens/create_service.rb
index adb7924f35e..31ba88af46c 100644
--- a/app/services/personal_access_tokens/create_service.rb
+++ b/app/services/personal_access_tokens/create_service.rb
@@ -13,7 +13,7 @@ module PersonalAccessTokens
def execute
return ServiceResponse.error(message: 'Not permitted to create') unless creation_permitted?
- token = target_user.personal_access_tokens.create(params.slice(*allowed_params))
+ token = target_user.personal_access_tokens.create(personal_access_token_params)
if token.persisted?
log_event(token)
@@ -31,13 +31,17 @@ module PersonalAccessTokens
attr_reader :target_user, :ip_address
- def allowed_params
- [
- :name,
- :impersonation,
- :scopes,
- :expires_at
- ]
+ def personal_access_token_params
+ {
+ name: params[:name],
+ impersonation: params[:impersonation] || false,
+ scopes: params[:scopes],
+ expires_at: pat_expiration
+ }
+ end
+
+ def pat_expiration
+ params[:expires_at].presence || PersonalAccessToken::MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS.days.from_now
end
def creation_permitted?
diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb
index b184c2f8f58..1fea894a599 100644
--- a/app/services/resource_access_tokens/create_service.rb
+++ b/app/services/resource_access_tokens/create_service.rb
@@ -97,7 +97,7 @@ module ResourceAccessTokens
name: params[:name] || "#{resource_type}_bot",
impersonation: false,
scopes: params[:scopes] || default_scopes,
- expires_at: params[:expires_at] || nil
+ expires_at: pat_expiration
}
end
@@ -106,10 +106,10 @@ module ResourceAccessTokens
end
def create_membership(resource, user, access_level)
- resource.add_member(user, access_level, expires_at: default_pat_expiration)
+ resource.add_member(user, access_level, expires_at: pat_expiration)
end
- def default_pat_expiration
+ def pat_expiration
params[:expires_at].presence || PersonalAccessToken::MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS.days.from_now
end
diff --git a/config/feature_flags/development/adherence_report_ui.yml b/config/feature_flags/development/adherence_report_ui.yml
new file mode 100644
index 00000000000..5648299c689
--- /dev/null
+++ b/config/feature_flags/development/adherence_report_ui.yml
@@ -0,0 +1,8 @@
+---
+name: adherence_report_ui
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122374
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/414495
+milestone: '16.1'
+type: development
+group: group::compliance
+default_enabled: false
diff --git a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
index 9358d756644..bfef9b0ed10 100755
--- a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
@@ -179,6 +179,7 @@ options:
- p_ci_templates_katalon
- p_ci_templates_terraform_module_base
- p_ci_templates_terraform_module
+ - p_ci_templates_pages_zola
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20230527152402_p_ci_templates_pages_zola_monthly.yml b/config/metrics/counts_28d/20230527152402_p_ci_templates_pages_zola_monthly.yml
new file mode 100644
index 00000000000..778b70d699d
--- /dev/null
+++ b/config/metrics/counts_28d/20230527152402_p_ci_templates_pages_zola_monthly.yml
@@ -0,0 +1,24 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_pages_zola_monthly
+description: Count of pipelines using the Zola Pages template
+product_section: ''
+product_stage: ''
+product_group: ''
+value_type: number
+status: active
+milestone: "16.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121946
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_pages_zola
diff --git a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
index 64ef9858a64..3e1becde7d7 100755
--- a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
@@ -180,6 +180,7 @@ options:
- p_ci_templates_katalon
- p_ci_templates_terraform_module_base
- p_ci_templates_terraform_module
+ - p_ci_templates_pages_zola
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20230527152358_p_ci_templates_pages_zola_weekly.yml b/config/metrics/counts_7d/20230527152358_p_ci_templates_pages_zola_weekly.yml
new file mode 100644
index 00000000000..d2cde6a4510
--- /dev/null
+++ b/config/metrics/counts_7d/20230527152358_p_ci_templates_pages_zola_weekly.yml
@@ -0,0 +1,24 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_pages_zola_weekly
+description: Count of pipelines using the Zola Pages template
+product_section: ''
+product_stage: ''
+product_group: ''
+value_type: number
+status: active
+milestone: "16.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121946
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_pages_zola
diff --git a/db/fixtures/development/25_api_personal_access_token.rb b/db/fixtures/development/25_api_personal_access_token.rb
index 1413f468be1..10f7d311419 100644
--- a/db/fixtures/development/25_api_personal_access_token.rb
+++ b/db/fixtures/development/25_api_personal_access_token.rb
@@ -12,6 +12,7 @@ Gitlab::Seeder.quiet do
}
user.personal_access_tokens.build(params).tap do |pat|
+ pat.expires_at = 365.days.from_now
pat.set_token(token)
pat.save!
end
diff --git a/db/post_migrate/20230522073230_add_not_null_constraint_to_personal_access_tokens_expires_at.rb b/db/post_migrate/20230522073230_add_not_null_constraint_to_personal_access_tokens_expires_at.rb
new file mode 100644
index 00000000000..74dddb68d3b
--- /dev/null
+++ b/db/post_migrate/20230522073230_add_not_null_constraint_to_personal_access_tokens_expires_at.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddNotNullConstraintToPersonalAccessTokensExpiresAt < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ def up
+ add_not_null_constraint :personal_access_tokens, :expires_at, validate: false
+ end
+
+ def down
+ remove_not_null_constraint :personal_access_tokens, :expires_at
+ end
+end
diff --git a/db/schema_migrations/20230522073230 b/db/schema_migrations/20230522073230
new file mode 100644
index 00000000000..dee1babf25b
--- /dev/null
+++ b/db/schema_migrations/20230522073230
@@ -0,0 +1 @@
+d630b2bbfbb4ac030da8020745005bf7326b337ea9dbf4a57130e95d1824b780 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index d510a6ab9fb..d454f9d06cd 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -26899,6 +26899,9 @@ ALTER TABLE users
ALTER TABLE vulnerability_scanners
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
+ALTER TABLE personal_access_tokens
+ ADD CONSTRAINT check_b8d60815eb CHECK ((expires_at IS NOT NULL)) NOT VALID;
+
ALTER TABLE sprints
ADD CONSTRAINT check_ccd8a1eae0 CHECK ((start_date IS NOT NULL)) NOT VALID;
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 2547851dbb3..7661f2ec9a6 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -23733,7 +23733,7 @@ Represents a state transition of a vulnerability.
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="vulnerabilitystatetransitiontypeauthor"></a>`author` | [`UserCore!`](#usercore) | User who changed the state of the vulnerability. |
+| <a id="vulnerabilitystatetransitiontypeauthor"></a>`author` | [`UserCore`](#usercore) | User who changed the state of the vulnerability. |
| <a id="vulnerabilitystatetransitiontypecomment"></a>`comment` | [`String`](#string) | Comment for the state change. |
| <a id="vulnerabilitystatetransitiontypecreatedat"></a>`createdAt` | [`Time!`](#time) | Time of the state change of the vulnerability. |
| <a id="vulnerabilitystatetransitiontypedismissalreason"></a>`dismissalReason` | [`VulnerabilityDismissalReason`](#vulnerabilitydismissalreason) | Reason for the dismissal. |
diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md
index b9c2ee409b8..c446d89da41 100644
--- a/doc/ci/jobs/index.md
+++ b/doc/ci/jobs/index.md
@@ -342,7 +342,7 @@ In the example above:
job log, but they are displayed in the raw job log. To see them, in the upper-right corner
of the job log, select **Show complete raw** (**{doc-text}**).
- `\r`: carriage return.
- - `\e[0K`: clear line ANSI escape code.
+ - `\e[0K`: clear line ANSI escape sequence (`\e[K` does not work, the `0` must be included).
Sample raw job log:
diff --git a/doc/development/cicd/cicd_tables.md b/doc/development/cicd/cicd_tables.md
index b246328a817..8cfb0faca00 100644
--- a/doc/development/cicd/cicd_tables.md
+++ b/doc/development/cicd/cicd_tables.md
@@ -29,7 +29,7 @@ Here is an example on how to use database helpers to create a new table and fore
end
add_concurrent_partitioned_foreign_key(
- :p_ci_examples, :ci_builds,
+ :p_ci_examples, :p_ci_builds,
column: [:partition_id, :build_id],
target_column: [:partition_id, :id],
on_update: :cascade,
@@ -51,7 +51,7 @@ When creating the routing table:
- The table name must start with the `p_` prefix. There are analyzers in place to ensure that all queries go
through the routing tables and do not access the partitions directly.
- Each new table needs a `partition_id` column and its value must equal
- the value from the related association. In this example, that is `ci_builds`. All resources
+ the value from the related association. In this example, that is `p_ci_builds`. All resources
belonging to a pipeline share the same `partition_id` value.
- The primary key must have the columns ordered this way to allow efficient
search only by `id`.
@@ -74,7 +74,7 @@ the application runs:
def up
with_lock_retries do
connection.execute(<<~SQL)
- LOCK TABLE ci_builds IN SHARE UPDATE EXCLUSIVE MODE;
+ LOCK TABLE p_ci_builds IN SHARE ROW EXCLUSIVE MODE;
LOCK TABLE ONLY p_ci_examples IN ACCESS EXCLUSIVE MODE;
SQL
@@ -92,7 +92,7 @@ Partitions are created in `gitlab_partitions_dynamic` schema.
When creating a partition, remember:
- Partition names do not use the `p_` prefix.
-- The default value for `partition_id` is `100`.
+- The starting value for `partition_id` is `100`.
## Cascade the partition value
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index ca6475566b3..e0fce2db84d 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -856,7 +856,7 @@ Sometimes they are more precise and will be maintained more actively.
For each external link you add, weigh the customer benefit with the maintenance difficulties.
-### Links requiring permissions
+### Links that require permissions
Don't link directly to:
@@ -864,23 +864,26 @@ Don't link directly to:
- Project features that require [special permissions](../../../user/permissions.md)
to view.
-These fail for:
+These links fail for:
- Those without sufficient permissions.
- Automated link checkers.
-Instead:
+If you must use one of these links:
-- To reduce confusion, mention in the text that the information is either:
- - Contained in a confidential issue.
- - Requires special permission to a project to view.
-- Provide a link in back ticks (`` ` ``) so that those with access to the issue
- can navigate to it.
+- Mention that the information is confidential or requires specific permissions.
+- Put the link in backticks, so that it does not cause link checkers to fail.
-Example:
+Examples:
```markdown
-For more information, see the [confidential issue](../../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-foss/-/issues/<issue_number>`.
+GitLab team members can view more information in this confidential issue:
+`https://gitlab.com/gitlab-org/gitlab/-/issues/<issue_number>`
+```
+
+```markdown
+Users with the Maintainer role for the project can use the pipeline editor:
+`https://gitlab.com/gitlab-org/gitlab/-/ci/editor`
```
### Link to specific lines of code
diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index d519fda764f..ce3a5ee9916 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -74,7 +74,7 @@ To purge files from a GitLab repository:
1. Clone a fresh copy of the repository from the bundle using `--bare` and `--mirror` options:
```shell
- git clone --bare /path/to/project.bundle
+ git clone --bare --mirror /path/to/project.bundle
```
1. Go to the `project.git` directory:
@@ -134,6 +134,12 @@ To purge files from a GitLab repository:
Repeat this step and all following steps (including the [repository cleanup](#repository-cleanup) step)
every time you run any `git filter-repo` command.
+1. To allow you to force push the changes you need to unset the mirror flag:
+
+ ```shell
+ git config --unset remote.origin.mirror
+ ```
+
1. Force push your changes to overwrite all branches on GitLab:
```shell
@@ -167,8 +173,6 @@ To purge files from a GitLab repository:
## Repository cleanup
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19376) in GitLab 11.6.
-
Repository cleanup allows you to upload a text file of objects and GitLab removes internal Git
references to these objects. You can use
[`git filter-repo`](https://github.com/newren/git-filter-repo) to produce a list of objects (in a
@@ -180,6 +184,10 @@ of the operation. This happens automatically, but submitting the cleanup request
fails if any writes are ongoing, so cancel any outstanding `git push`
operations before continuing.
+WARNING:
+Removing internal Git references results in associated merge request commits, pipelines, and changes details
+no longer being available.
+
To clean up a repository:
1. Go to the project for the repository.
diff --git a/lib/api/resource_access_tokens.rb b/lib/api/resource_access_tokens.rb
index b98ed5ec9ff..1ad5bc8d421 100644
--- a/lib/api/resource_access_tokens.rb
+++ b/lib/api/resource_access_tokens.rb
@@ -92,17 +92,30 @@ module API
success Entities::ResourceAccessTokenWithToken
end
params do
- requires :id, type: String, desc: "The #{source_type} ID", documentation: { example: 2 }
- requires :name, type: String, desc: "Resource access token name", documentation: { example: 'test' }
- requires :scopes, type: Array[String], values: ::Gitlab::Auth.resource_bot_scopes.map(&:to_s),
- desc: "The permissions of the token",
- documentation: { example: %w[api read_repository] }
- optional :access_level, type: Integer,
- values: ALLOWED_RESOURCE_ACCESS_LEVELS.values,
- default: Gitlab::Access::MAINTAINER,
- desc: "The access level of the token in the #{source_type}",
- documentation: { example: 40 }
- optional :expires_at, type: Date, desc: "The expiration date of the token", documentation: { example: '"2021-01-31' }
+ requires :id,
+ type: String,
+ desc: "The #{source_type} ID",
+ documentation: { example: 2 }
+ requires :name,
+ type: String,
+ desc: "Resource access token name",
+ documentation: { example: 'test' }
+ requires :scopes,
+ type: Array[String],
+ values: ::Gitlab::Auth.resource_bot_scopes.map(&:to_s),
+ desc: "The permissions of the token",
+ documentation: { example: %w[api read_repository] }
+ requires :expires_at,
+ type: Date,
+ desc: "The expiration date of the token",
+ default: PersonalAccessToken::MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS.days.from_now,
+ documentation: { example: '"2021-01-31' }
+ optional :access_level,
+ type: Integer,
+ values: ALLOWED_RESOURCE_ACCESS_LEVELS.values,
+ default: Gitlab::Access::MAINTAINER,
+ desc: "The access level of the token in the #{source_type}",
+ documentation: { example: 40 }
end
post ':id/access_tokens' do
resource = find_source(source_type, params[:id])
diff --git a/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml b/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml
index 7f81755348c..3d053d4d78c 100644
--- a/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml
@@ -8,9 +8,9 @@
code_quality:
stage: test
- image: "cirrusci/flutter:1.22.5"
+ image: "ghcr.io/cirruslabs/flutter:3.10.3"
before_script:
- - pub global activate dart_code_metrics
+ - flutter pub global activate dart_code_metrics
- export PATH="$PATH:$HOME/.pub-cache/bin"
script:
- metrics lib -r codeclimate > gl-code-quality-report.json
@@ -20,9 +20,9 @@ code_quality:
test:
stage: test
- image: "cirrusci/flutter:1.22.5"
+ image: "ghcr.io/cirruslabs/flutter:3.10.3"
before_script:
- - pub global activate junitreport
+ - flutter pub global activate junitreport
- export PATH="$PATH:$HOME/.pub-cache/bin"
script:
- flutter test --machine --coverage | tojunit -o report.xml
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index eebc1926432..f4a13d61ba2 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.49.0'
+ DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.50.0'
.dast-auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index cd1e3a25b94..c1a3daa7f5b 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.49.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.50.0'
.auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
index 489a7aab22f..a3c7c6baf02 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.49.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.50.0'
.auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/lib/gitlab/ci/templates/Pages/Zola.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Zola.gitlab-ci.yml
new file mode 100644
index 00000000000..c2c890846b9
--- /dev/null
+++ b/lib/gitlab/ci/templates/Pages/Zola.gitlab-ci.yml
@@ -0,0 +1,30 @@
+# To contribute improvements to CI/CD templates, please follow the Development guide at:
+# https://docs.gitlab.com/ee/development/cicd/templates.html
+# This specific template is located at:
+# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Pages/Zola.gitlab-ci.yml
+
+# Prefer to copy-paste this template instead of include it to ensure forward compatibility
+
+---
+# From: https://www.getzola.org/documentation/deployment/gitlab-pages/
+# Source template is slightly modified to be self-contained
+
+pages:
+ image: alpine:latest
+ variables:
+ # This variable will ensure that the CI runner pulls in your theme from the submodule
+ GIT_SUBMODULE_STRATEGY: recursive
+ before_script:
+ # Install the zola package from the alpine community repositories
+ - apk add --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ zola
+ script:
+ # Execute zola build
+ - zola build --base-url "$CI_PAGES_URL"
+ artifacts:
+ paths:
+ # Path of our artifacts
+ - public
+ # This config will only publish changes that are pushed on the default branch
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 0c67b9fa078..9b2256a4a6e 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -123,8 +123,10 @@ module Gitlab
end
def tree_entries(repository, revision, path, recursive, skip_flat_paths, pagination_params)
- pagination_params ||= {}
- pagination_params[:limit] ||= TREE_ENTRIES_DEFAULT_LIMIT
+ unless pagination_params.nil? && recursive
+ pagination_params ||= {}
+ pagination_params[:limit] ||= TREE_ENTRIES_DEFAULT_LIMIT
+ end
request = Gitaly::GetTreeEntriesRequest.new(
repository: @gitaly_repo,
diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
index f685f0d65d9..c3e1c34151b 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -307,3 +307,5 @@
aggregation: weekly
- name: p_ci_templates_terraform_module
aggregation: weekly
+- name: p_ci_templates_pages_zola
+ aggregation: weekly
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 9dd5593e9bb..9a6218e486a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1084,6 +1084,9 @@ msgid_plural "%{selectedProjectsCount} projects"
msgstr[0] ""
msgstr[1] ""
+msgid "%{size} B"
+msgstr ""
+
msgid "%{size} GiB"
msgstr ""
@@ -1093,9 +1096,6 @@ msgstr ""
msgid "%{size} MiB"
msgstr ""
-msgid "%{size} bytes"
-msgstr ""
-
msgid "%{sourceBranch} into %{targetBranch}"
msgstr ""
@@ -1538,7 +1538,7 @@ msgstr ""
msgid "/day"
msgstr ""
-msgid "0 bytes"
+msgid "0 B"
msgstr ""
msgid "1 Code quality finding"
@@ -11483,6 +11483,9 @@ msgstr ""
msgid "Compliance Report|Frameworks"
msgstr ""
+msgid "Compliance Report|Standards Adherence"
+msgstr ""
+
msgid "Compliance Report|Violations"
msgstr ""
diff --git a/qa/qa/fixtures/package_managers/npm/npm_install_package_group.yaml.erb b/qa/qa/fixtures/package_managers/npm/npm_install_package_group.yaml.erb
new file mode 100644
index 00000000000..a5ec4f298e2
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/npm/npm_install_package_group.yaml.erb
@@ -0,0 +1,21 @@
+image: node:latest
+
+stages:
+ - install
+
+install:
+ stage: install
+ script:
+ - "npm config set @<%= registry_scope %>:registry <%= gitlab_address_with_port %>/api/v4/groups/<%= another_project.group.id %>/-/packages/npm/"
+ - "npm install <%= package.name %>"
+ cache:
+ key: ${CI_COMMIT_REF_NAME}
+ paths:
+ - node_modules/
+ artifacts:
+ paths:
+ - node_modules/
+ only:
+ - "<%= another_project.default_branch %>"
+ tags:
+ - "runner-for-<%= another_project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/npm/npm_upload_package_group.yaml.erb b/qa/qa/fixtures/package_managers/npm/npm_upload_package_group.yaml.erb
new file mode 100644
index 00000000000..13c00cd17c4
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/npm/npm_upload_package_group.yaml.erb
@@ -0,0 +1,14 @@
+image: node:latest
+
+stages:
+ - deploy
+
+deploy:
+ stage: deploy
+ script:
+ - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=<%= auth_token %>">.npmrc
+ - npm publish
+ only:
+ - "<%= project.default_branch %>"
+ tags:
+ - "runner-for-<%= project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/npm/package_instance.json.erb b/qa/qa/fixtures/package_managers/npm/package.json.erb
index 46fecf97e2c..46fecf97e2c 100644
--- a/qa/qa/fixtures/package_managers/npm/package_instance.json.erb
+++ b/qa/qa/fixtures/package_managers/npm/package.json.erb
diff --git a/qa/qa/fixtures/package_managers/npm/package_project.json.erb b/qa/qa/fixtures/package_managers/npm/package_project.json.erb
deleted file mode 100644
index 46fecf97e2c..00000000000
--- a/qa/qa/fixtures/package_managers/npm/package_project.json.erb
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "<%= package.name %>",
- "version": "1.0.0",
- "description": "Example package for GitLab npm registry",
- "publishConfig": {
- "@<%= registry_scope %>:registry": "<%= gitlab_address_with_port %>/api/v4/projects/<%= project.id %>/packages/npm/"
- }
-} \ No newline at end of file
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_group_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_group_level_spec.rb
new file mode 100644
index 00000000000..3f0696fd00c
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_group_level_spec.rb
@@ -0,0 +1,175 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package' do
+ describe 'Package Registry', :skip_live_env, :orchestrated, :packages, :object_storage,
+ product_group: :package_registry do
+ describe 'npm group level endpoint' do
+ using RSpec::Parameterized::TableSyntax
+ include Runtime::Fixtures
+ include Support::Helpers::MaskToken
+
+ let!(:registry_scope) { Runtime::Namespace.sandbox_name }
+ let!(:personal_access_token) do
+ Flow::Login.sign_in unless Page::Main::Menu.perform(&:signed_in?)
+
+ Resource::PersonalAccessToken.fabricate!.token
+ end
+
+ let(:project_deploy_token) do
+ Resource::ProjectDeployToken.fabricate_via_api! do |deploy_token|
+ deploy_token.name = 'npm-deploy-token'
+ deploy_token.project = project
+ deploy_token.scopes = %w[
+ read_repository
+ read_package_registry
+ write_package_registry
+ ]
+ end
+ end
+
+ let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
+ let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
+ let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
+
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'npm-group-level-publish'
+ end
+ end
+
+ let!(:another_project) do
+ Resource::Project.fabricate_via_api! do |another_project|
+ another_project.name = 'npm-group-level-install'
+ another_project.group = project.group
+ end
+ end
+
+ let!(:runner) do
+ Resource::GroupRunner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.group.name}"]
+ runner.executor = :docker
+ runner.group = project.group
+ end
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "@#{registry_scope}/#{project.name}-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
+ after do
+ package.remove_via_api!
+ runner.remove_via_api!
+ project.remove_via_api!
+ another_project.remove_via_api!
+ end
+
+ where(:case_name, :authentication_token_type, :token_name, :testcase) do
+ 'using personal access token' | :personal_access_token | 'Personal Access Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/413760'
+ 'using ci job token' | :ci_job_token | 'CI Job Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/413761'
+ 'using project deploy token' | :project_deploy_token | 'Deploy Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/413762'
+ end
+
+ with_them do
+ let(:auth_token) do
+ case authentication_token_type
+ when :personal_access_token
+ use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: project)
+ use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: another_project)
+ when :ci_job_token
+ '${CI_JOB_TOKEN}'
+ when :project_deploy_token
+ use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: project)
+ use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: another_project)
+ end
+ end
+
+ it 'push and pull a npm package via CI', testcase: params[:testcase] do
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ npm_upload_yaml = ERB.new(read_fixture('package_managers/npm',
+ 'npm_upload_package_group.yaml.erb')).result(binding)
+ package_json = ERB.new(read_fixture('package_managers/npm', 'package.json.erb')).result(binding)
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add files'
+ commit.add_files([
+ {
+ file_path: '.gitlab-ci.yml',
+ content: npm_upload_yaml
+ },
+ {
+ file_path: 'package.json',
+ content: package_json
+ }
+ ])
+ end
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ npm_install_yaml = ERB.new(read_fixture('package_managers/npm',
+ 'npm_install_package_group.yaml.erb')).result(binding)
+
+ commit.project = another_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ {
+ file_path: '.gitlab-ci.yml',
+ content: npm_install_yaml
+ }
+ ])
+ end
+ end
+
+ another_project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ job.click_browse_button
+ end
+
+ Page::Project::Artifact::Show.perform do |artifacts|
+ artifacts.go_to_directory('node_modules')
+ artifacts.go_to_directory("@#{registry_scope}")
+ expect(artifacts).to have_content(project.name.to_s)
+ end
+
+ project.visit!
+ Page::Project::Menu.perform(&:go_to_package_registry)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform do |show|
+ expect(show).to have_package_info(package.name, "1.0.0")
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
index 4a8b95717d0..83abc030ada 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
@@ -90,7 +90,7 @@ module QA
it 'push and pull a npm package via CI', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
npm_upload_yaml = ERB.new(read_fixture('package_managers/npm', 'npm_upload_package_instance.yaml.erb')).result(binding)
- package_json = ERB.new(read_fixture('package_managers/npm', 'package_instance.json.erb')).result(binding)
+ package_json = ERB.new(read_fixture('package_managers/npm', 'package.json.erb')).result(binding)
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
index e913df0957d..db68cc9ad2d 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
@@ -81,7 +81,7 @@ module QA
it 'push and pull a npm package via CI', testcase: params[:testcase] do
Resource::Repository::Commit.fabricate_via_api! do |commit|
npm_upload_install_yaml = ERB.new(read_fixture('package_managers/npm', 'npm_upload_install_package_project.yaml.erb')).result(binding)
- package_json = ERB.new(read_fixture('package_managers/npm', 'package_project.json.erb')).result(binding)
+ package_json = ERB.new(read_fixture('package_managers/npm', 'package.json.erb')).result(binding)
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
diff --git a/spec/factories/personal_access_tokens.rb b/spec/factories/personal_access_tokens.rb
index a140011941f..c7361b11633 100644
--- a/spec/factories/personal_access_tokens.rb
+++ b/spec/factories/personal_access_tokens.rb
@@ -5,7 +5,7 @@ FactoryBot.define do
user
sequence(:name) { |n| "PAT #{n}" }
revoked { false }
- expires_at { 5.days.from_now }
+ expires_at { 30.days.from_now }
scopes { ['api'] }
impersonation { false }
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 29ade6514be..b69452069c0 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -43,7 +43,7 @@ describe('diffs/components/app', () => {
let wrapper;
let mock;
- function createComponent(props = {}, extendStore = () => {}, provisions = {}) {
+ function createComponent(props = {}, extendStore = () => {}, provisions = {}, baseConfig = {}) {
const provide = {
...provisions,
glFeatures: {
@@ -57,20 +57,24 @@ describe('diffs/components/app', () => {
extendStore(store);
+ store.dispatch('diffs/setBaseConfig', {
+ endpoint: TEST_ENDPOINT,
+ endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
+ endpointBatch: `${TEST_HOST}/diff/endpointBatch`,
+ endpointDiffForPath: TEST_ENDPOINT,
+ projectPath: 'namespace/project',
+ dismissEndpoint: '',
+ showSuggestPopover: true,
+ mrReviews: {},
+ ...baseConfig,
+ });
+
wrapper = shallowMount(App, {
propsData: {
- endpoint: TEST_ENDPOINT,
- endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
- endpointBatch: `${TEST_HOST}/diff/endpointBatch`,
- endpointDiffForPath: TEST_ENDPOINT,
endpointCoverage: `${TEST_HOST}/diff/endpointCoverage`,
endpointCodequality: '',
- projectPath: 'namespace/project',
currentUser: {},
changesEmptyStateIllustration: '',
- dismissEndpoint: '',
- showSuggestPopover: true,
- fileByFileUserPreference: false,
...props,
},
provide,
@@ -653,13 +657,18 @@ describe('diffs/components/app', () => {
describe('file-by-file', () => {
it('renders a single diff', async () => {
- createComponent({ fileByFileUserPreference: true }, ({ state }) => {
- state.diffs.treeEntries = {
- 123: { type: 'blob', fileHash: '123' },
- 312: { type: 'blob', fileHash: '312' },
- };
- state.diffs.diffFiles.push({ file_hash: '312' });
- });
+ createComponent(
+ undefined,
+ ({ state }) => {
+ state.diffs.treeEntries = {
+ 123: { type: 'blob', fileHash: '123' },
+ 312: { type: 'blob', fileHash: '312' },
+ };
+ state.diffs.diffFiles.push({ file_hash: '312' });
+ },
+ undefined,
+ { viewDiffsFileByFile: true },
+ );
await nextTick();
@@ -671,12 +680,17 @@ describe('diffs/components/app', () => {
const paginator = () => fileByFileNav().findComponent(GlPagination);
it('sets previous button as disabled', async () => {
- createComponent({ fileByFileUserPreference: true }, ({ state }) => {
- state.diffs.treeEntries = {
- 123: { type: 'blob', fileHash: '123' },
- 312: { type: 'blob', fileHash: '312' },
- };
- });
+ createComponent(
+ undefined,
+ ({ state }) => {
+ state.diffs.treeEntries = {
+ 123: { type: 'blob', fileHash: '123' },
+ 312: { type: 'blob', fileHash: '312' },
+ };
+ },
+ undefined,
+ { viewDiffsFileByFile: true },
+ );
await nextTick();
@@ -685,13 +699,18 @@ describe('diffs/components/app', () => {
});
it('sets next button as disabled', async () => {
- createComponent({ fileByFileUserPreference: true }, ({ state }) => {
- state.diffs.treeEntries = {
- 123: { type: 'blob', fileHash: '123' },
- 312: { type: 'blob', fileHash: '312' },
- };
- state.diffs.currentDiffFileId = '312';
- });
+ createComponent(
+ undefined,
+ ({ state }) => {
+ state.diffs.treeEntries = {
+ 123: { type: 'blob', fileHash: '123' },
+ 312: { type: 'blob', fileHash: '312' },
+ };
+ state.diffs.currentDiffFileId = '312';
+ },
+ undefined,
+ { viewDiffsFileByFile: true },
+ );
await nextTick();
@@ -700,10 +719,15 @@ describe('diffs/components/app', () => {
});
it("doesn't display when there's fewer than 2 files", async () => {
- createComponent({ fileByFileUserPreference: true }, ({ state }) => {
- state.diffs.treeEntries = { 123: { type: 'blob', fileHash: '123' } };
- state.diffs.currentDiffFileId = '123';
- });
+ createComponent(
+ undefined,
+ ({ state }) => {
+ state.diffs.treeEntries = { 123: { type: 'blob', fileHash: '123' } };
+ state.diffs.currentDiffFileId = '123';
+ },
+ undefined,
+ { viewDiffsFileByFile: true },
+ );
await nextTick();
@@ -717,13 +741,18 @@ describe('diffs/components/app', () => {
`(
'calls navigateToDiffFileIndex with $index when $link is clicked',
async ({ currentDiffFileId, targetFile }) => {
- createComponent({ fileByFileUserPreference: true }, ({ state }) => {
- state.diffs.treeEntries = {
- 123: { type: 'blob', fileHash: '123', filePaths: { old: '1234', new: '123' } },
- 312: { type: 'blob', fileHash: '312', filePaths: { old: '3124', new: '312' } },
- };
- state.diffs.currentDiffFileId = currentDiffFileId;
- });
+ createComponent(
+ undefined,
+ ({ state }) => {
+ state.diffs.treeEntries = {
+ 123: { type: 'blob', fileHash: '123', filePaths: { old: '1234', new: '123' } },
+ 312: { type: 'blob', fileHash: '312', filePaths: { old: '3124', new: '312' } },
+ };
+ state.diffs.currentDiffFileId = currentDiffFileId;
+ },
+ undefined,
+ { viewDiffsFileByFile: true },
+ );
await nextTick();
diff --git a/spec/frontend/lib/utils/number_utility_spec.js b/spec/frontend/lib/utils/number_utility_spec.js
index d2591cd2328..07e3e2f0422 100644
--- a/spec/frontend/lib/utils/number_utility_spec.js
+++ b/spec/frontend/lib/utils/number_utility_spec.js
@@ -109,8 +109,8 @@ describe('Number Utils', () => {
describe('numberToHumanSize', () => {
it('should return bytes', () => {
- expect(numberToHumanSize(654)).toEqual('654 bytes');
- expect(numberToHumanSize(-654)).toEqual('-654 bytes');
+ expect(numberToHumanSize(654)).toEqual('654 B');
+ expect(numberToHumanSize(-654)).toEqual('-654 B');
});
it('should return KiB', () => {
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js
index 1e9b9b1ce47..d5a87945c16 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js
@@ -132,7 +132,7 @@ describe('Harbor artifact list row', () => {
},
});
- expect(findByTestId('size').text()).toBe('0 bytes');
+ expect(findByTestId('size').text()).toBe('0 B');
});
});
});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
index 148e87699f1..7f56d3e216c 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
@@ -51,7 +51,7 @@ describe('PackageTitle', () => {
it('correctly calculates the size', async () => {
await createComponent();
- expect(packageSize().props('text')).toBe('300 bytes');
+ expect(packageSize().props('text')).toBe('300 B');
});
});
diff --git a/spec/frontend/super_sidebar/components/help_center_spec.js b/spec/frontend/super_sidebar/components/help_center_spec.js
index 4c3e6400daa..23903627f0a 100644
--- a/spec/frontend/super_sidebar/components/help_center_spec.js
+++ b/spec/frontend/super_sidebar/components/help_center_spec.js
@@ -25,6 +25,7 @@ describe('HelpCenter component', () => {
};
const withinComponent = () => within(wrapper.element);
const findButton = (name) => withinComponent().getByRole('button', { name });
+ const findNotificationDot = () => wrapper.findByTestId('notification-dot');
// eslint-disable-next-line no-shadow
const createWrapper = (sidebarData) => {
@@ -203,8 +204,8 @@ describe('HelpCenter component', () => {
createWrapper({ ...sidebarData, display_whats_new: false });
});
- it('is false', () => {
- expect(wrapper.vm.showWhatsNewNotification).toBe(false);
+ it('does not render notification dot', () => {
+ expect(findNotificationDot().exists()).toBe(false);
});
});
@@ -215,8 +216,8 @@ describe('HelpCenter component', () => {
createWrapper({ ...sidebarData, display_whats_new: true });
});
- it('is true', () => {
- expect(wrapper.vm.showWhatsNewNotification).toBe(true);
+ it('renders notification dot', () => {
+ expect(findNotificationDot().exists()).toBe(true);
});
describe('when "What\'s new" drawer got opened', () => {
@@ -224,8 +225,8 @@ describe('HelpCenter component', () => {
findButton("What's new 5").click();
});
- it('is false', () => {
- expect(wrapper.vm.showWhatsNewNotification).toBe(false);
+ it('does not render notification dot', () => {
+ expect(findNotificationDot().exists()).toBe(false);
});
});
@@ -235,8 +236,8 @@ describe('HelpCenter component', () => {
createWrapper({ ...sidebarData, display_whats_new: true });
});
- it('is false', () => {
- expect(wrapper.vm.showWhatsNewNotification).toBe(false);
+ it('does not render notification dot', () => {
+ expect(findNotificationDot().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend_integration/diffs/diffs_interopability_spec.js b/spec/frontend_integration/diffs/diffs_interopability_spec.js
index 5017fb8c49d..c5bd77adf8f 100644
--- a/spec/frontend_integration/diffs/diffs_interopability_spec.js
+++ b/spec/frontend_integration/diffs/diffs_interopability_spec.js
@@ -3,6 +3,7 @@ import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { stubPerformanceWebAPI } from 'helpers/performance';
import initDiffsApp from '~/diffs';
+import { initMrStateLazyLoad } from '~/mr_notes/init';
import { createStore } from '~/mr_notes/stores';
import {
getDiffCodePart,
@@ -53,23 +54,35 @@ const startDiffsApp = () => {
endpointBatch: `${TEST_BASE_URL}diffs_batch.json`,
projectPath: TEST_PROJECT_PATH,
helpPagePath: '/help',
- currentUserData: 'null',
+ currentUserData: '{}',
changesEmptyStateIllustration: '',
isFluidLayout: 'false',
dismissEndpoint: '',
showSuggestPopover: 'false',
showWhitespaceDefault: 'true',
- viewDiffsFileByFile: 'false',
+ fileByFileDefault: 'false',
defaultSuggestionCommitMessage: 'Lorem ipsum',
});
- const store = createStore();
-
- const vm = initDiffsApp(store);
+ const notesEl = document.createElement('div');
+ notesEl.id = 'js-vue-mr-discussions';
+ document.body.appendChild(notesEl);
+ Object.assign(notesEl.dataset, {
+ noteableData: '{ "current_user": {} }',
+ notesData: '{}',
+ currentUserData: '{}',
+ });
- store.dispatch('setActiveTab', 'diffs');
+ window.mrTabs = {
+ getCurrentAction: () => 'diffs',
+ eventHub: {
+ $on() {},
+ },
+ };
+ const store = createStore();
+ initMrStateLazyLoad(store);
- return vm;
+ return initDiffsApp(store);
};
describe('diffs third party interoperability', () => {
@@ -117,7 +130,7 @@ describe('diffs third party interoperability', () => {
${'parallel view right side'} | ${'parallel'} | ${'.diff-tr.line_holder'} | ${'.diff-td.line_content.right-side'} | ${EXPECT_PARALLEL_RIGHT_SIDE}
`('$desc', ({ view, rowSelector, codeSelector, expectation }) => {
beforeEach(async () => {
- setWindowLocation(`${TEST_HOST}/${TEST_BASE_URL}/diffs?view=${view}`);
+ setWindowLocation(`${TEST_HOST}${TEST_BASE_URL}diffs?view=${view}`);
vm = startDiffsApp();
diff --git a/spec/lib/api/entities/personal_access_token_spec.rb b/spec/lib/api/entities/personal_access_token_spec.rb
index 7f79cc80573..039b5502231 100644
--- a/spec/lib/api/entities/personal_access_token_spec.rb
+++ b/spec/lib/api/entities/personal_access_token_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe API::Entities::PersonalAccessToken do
describe '#as_json' do
let_it_be(:user) { create(:user) }
- let_it_be(:token) { create(:personal_access_token, user: user, expires_at: nil) }
+ let_it_be(:token) { create(:personal_access_token, user: user) }
let(:entity) { described_class.new(token) }
diff --git a/spec/lib/gitlab/ci/templates/Pages/zola_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Pages/zola_gitlab_ci_yaml_spec.rb
new file mode 100644
index 00000000000..4f80ae0054b
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/Pages/zola_gitlab_ci_yaml_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Pages/Zola.gitlab-ci.yml', feature_category: :pages do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Pages/Zola') }
+
+ describe 'the created pipeline' do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.first_owner }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: project.default_branch) }
+ let(:pipeline) { service.execute(:push).payload }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template.content)
+ allow(Ci::BuildScheduleWorker).to receive(:perform).and_return(true)
+ end
+
+ it 'creates "pages" job' do
+ expect(build_names).to include('pages')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index 05205ab6d6a..52652caa7f6 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -208,6 +208,19 @@ RSpec.describe Gitlab::GitalyClient::CommitService, feature_category: :gitaly do
is_expected.to eq([[], nil])
end
+ context 'when recursive is "true"' do
+ let(:recursive) { true }
+
+ it 'sends a get_tree_entries message without the limit' do
+ expect_any_instance_of(Gitaly::CommitService::Stub)
+ .to receive(:get_tree_entries)
+ .with(gitaly_request_with_params({ pagination_params: nil }), kind_of(Hash))
+ .and_return([])
+
+ is_expected.to eq([[], nil])
+ end
+ end
+
context 'with UTF-8 params strings' do
let(:revision) { "branch\u011F" }
let(:path) { "foo/\u011F.txt" }
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index 7367577914c..70123eaac26 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -130,7 +130,7 @@ RSpec.describe PersonalAccessToken, 'TokenAuthenticatable' do
let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
let(:user) { create(:user) }
let(:personal_access_token) do
- described_class.new(name: 'test-pat-01', user_id: user.id, scopes: [:api], token_digest: token_digest)
+ described_class.new(name: 'test-pat-01', user_id: user.id, scopes: [:api], token_digest: token_digest, expires_at: 30.days.from_now)
end
before do
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index 5ba9597a519..8e86518912c 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -259,6 +259,13 @@ RSpec.describe PersonalAccessToken, feature_category: :system_access do
context 'validates expires_at' do
let(:max_expiration_date) { described_class::MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS.days.from_now }
+ it "can't be blank" do
+ personal_access_token.expires_at = nil
+
+ expect(personal_access_token).not_to be_valid
+ expect(personal_access_token.errors[:expires_at].first).to eq("can't be blank")
+ end
+
context 'when expires_in is less than MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS days' do
it 'is valid' do
personal_access_token.expires_at = max_expiration_date - 1.day
@@ -285,11 +292,10 @@ RSpec.describe PersonalAccessToken, feature_category: :system_access do
let_it_be(:not_revoked_nil_token) { create(:personal_access_token, revoked: nil) }
let_it_be(:expired_token) { create(:personal_access_token, :expired) }
let_it_be(:not_expired_token) { create(:personal_access_token) }
- let_it_be(:never_expires_token) { create(:personal_access_token, expires_at: nil) }
- it 'includes non-revoked and non-expired tokens' do
+ it 'includes non-revoked tokens' do
expect(described_class.active)
- .to match_array([not_revoked_false_token, not_revoked_nil_token, not_expired_token, never_expires_token])
+ .to match_array([not_revoked_false_token, not_revoked_nil_token, not_expired_token])
end
end
@@ -414,22 +420,4 @@ RSpec.describe PersonalAccessToken, feature_category: :system_access do
end
end
end
-
- describe '#expires_at=' do
- let(:personal_access_token) { described_class.new }
-
- context 'expires_at set to empty value' do
- [nil, ""].each do |expires_in_value|
- it 'defaults to PersonalAccessToken::MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS' do
- personal_access_token.expires_at = expires_in_value
-
- freeze_time do
- expect(personal_access_token.expires_at).to eq(
- PersonalAccessToken::MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS.days.from_now.to_date
- )
- end
- end
- end
- end
- end
end
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 76172cf482d..619ffd8d41a 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -225,7 +225,8 @@ RSpec.describe API::Internal::Base, feature_category: :system_access do
params: {
key_id: key.id,
name: 'newtoken',
- scopes: %w(read_api read_repository)
+ scopes: %w(read_api read_repository),
+ expires_at: 365.days.from_now
},
headers: gitlab_shell_internal_api_request_header
diff --git a/spec/serializers/access_token_entity_base_spec.rb b/spec/serializers/access_token_entity_base_spec.rb
index 8a92a53d0c1..f310a3d4a99 100644
--- a/spec/serializers/access_token_entity_base_spec.rb
+++ b/spec/serializers/access_token_entity_base_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe AccessTokenEntityBase do
let_it_be(:user) { create(:user) }
- let_it_be(:token) { create(:personal_access_token, user: user, expires_at: nil) }
+ let_it_be(:token) { create(:personal_access_token, user: user) }
subject(:json) { described_class.new(token).as_json }
diff --git a/spec/services/personal_access_tokens/create_service_spec.rb b/spec/services/personal_access_tokens/create_service_spec.rb
index d80be5cccce..621211bc883 100644
--- a/spec/services/personal_access_tokens/create_service_spec.rb
+++ b/spec/services/personal_access_tokens/create_service_spec.rb
@@ -67,6 +67,13 @@ RSpec.describe PersonalAccessTokens::CreateService, feature_category: :system_ac
end
end
+ context 'with no expires_at set', :freeze_time do
+ let(:params) { { name: 'Test token', impersonation: false, scopes: [:no_valid] } }
+ let(:service) { described_class.new(current_user: user, target_user: user, params: params) }
+
+ it { expect(subject.payload[:personal_access_token].expires_at).to eq PersonalAccessToken::MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS.days.from_now.to_date }
+ end
+
context 'when invalid scope' do
let(:params) { { name: 'Test token', impersonation: false, scopes: [:no_valid], expires_at: Date.today + 1.month } }