Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
386dcdbe9d
commit
422294262e
|
|
@ -251,3 +251,34 @@ e2e:code-suggestions-eval-results:
|
|||
expose_as: 'Code Suggestions evaluation results'
|
||||
paths:
|
||||
- scores.csv
|
||||
|
||||
e2e:fulfillment-quarantine-report:
|
||||
extends:
|
||||
- .qa:rules:fulfillment-e2e-quarantine-report
|
||||
stage: qa
|
||||
before_script:
|
||||
- cd qa && bundle install
|
||||
- apt-get update && apt-get install -y jq
|
||||
variables:
|
||||
RSPEC_JSON: "tmp/rspec-fulfillment-quarantined.json"
|
||||
NOTES_API: "https://gitlab.com/api/v4/projects/$CI_MERGE_REQUEST_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes"
|
||||
USER_API: "https://gitlab.com/api/v4/user"
|
||||
FULFILLMENT_SPECS_PATH: "qa/specs/features/ee/browser_ui/11_fulfillment"
|
||||
script:
|
||||
- bundle exec rspec $FULFILLMENT_SPECS_PATH --tag quarantine --format json --out $RSPEC_JSON --dry-run
|
||||
- |
|
||||
if [[ -f $RSPEC_JSON && $(cat $RSPEC_JSON | jq ".examples[]") ]]
|
||||
then # quarantined tests found
|
||||
bot_user_id=$(curl $USER_API -H "PRIVATE-TOKEN: $PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE" | jq ".id")
|
||||
existing_comment=$(curl $NOTES_API -H "PRIVATE-TOKEN: $PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE" | jq ".[] | select((.author | .id | contains($bot_user_id)) and (.body | contains(\"# Quarantined Fulfillment QA E2E Tests\")))")
|
||||
if [[ ! -z $existing_comment ]]
|
||||
then
|
||||
echo 'MR comment already exists, doing nothing'
|
||||
else
|
||||
COMMENT_HEADER=$'# Quarantined Fulfillment QA E2E Tests\nThe following Fulfillment QA E2E tests are in quarantine. If your changes would be covered by these tests, please be sure to perform manual testing.\n'
|
||||
COMMENT_TABLE=$(cat $RSPEC_JSON | jq --raw-output '"|Description|Location|\n|---|---|\n" + ([.examples[] | "| \(.full_description) | \(.id) |\n"] | join(""))')
|
||||
curl --request POST $NOTES_API -H "PRIVATE-TOKEN: $PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE" --data-urlencode "body=$COMMENT_HEADER $COMMENT_TABLE"
|
||||
fi
|
||||
else
|
||||
echo 'No quarantined tests found'
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@
|
|||
.if-merge-request-and-specific-devops-stage: &if-merge-request-and-specific-devops-stage
|
||||
if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS =~ /devops::(create|govern|manage|plan|verify|package)/'
|
||||
|
||||
.if-merge-request-and-devops-fulfillment: &if-merge-request-and-devops-fulfillment
|
||||
if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS =~ /devops::fulfillment/'
|
||||
|
||||
.if-merge-request-not-approved: &if-merge-request-not-approved
|
||||
if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS !~ /pipeline:mr-approved/'
|
||||
|
||||
|
|
@ -1918,6 +1921,14 @@
|
|||
changes: *code-patterns
|
||||
allow_failure: true
|
||||
|
||||
.qa:rules:fulfillment-e2e-quarantine-report:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
when: never
|
||||
- <<: *if-merge-request-and-devops-fulfillment
|
||||
changes: *code-patterns
|
||||
allow_failure: true
|
||||
|
||||
###############
|
||||
# Rails rules #
|
||||
###############
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@
|
|||
// https://gitlab.com/gitlab-org/gitlab/-/issues/420777
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/421441
|
||||
|
||||
export const defaultOrganization = {
|
||||
id: 1,
|
||||
name: 'Default',
|
||||
web_url: '/-/organizations/default',
|
||||
avatar_url: null,
|
||||
};
|
||||
|
||||
export const organizations = [
|
||||
{
|
||||
id: 'gid://gitlab/Organizations::Organization/1',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,144 @@
|
|||
<script>
|
||||
import { GlDisclosureDropdown, GlAvatar, GlIcon, GlLoadingIcon } from '@gitlab/ui';
|
||||
import getCurrentUserOrganizations from '~/organizations/shared/graphql/queries/organizations.query.graphql';
|
||||
import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { defaultOrganization } from '~/organizations/mock_data';
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
AVATAR_SHAPE_OPTION_RECT,
|
||||
ITEM_LOADING: {
|
||||
id: 'loading',
|
||||
text: 'loading',
|
||||
extraAttrs: { disabled: true, class: 'gl-shadow-none!' },
|
||||
},
|
||||
ITEM_EMPTY: {
|
||||
id: 'empty',
|
||||
text: s__('Organization|No organizations available to switch to.'),
|
||||
extraAttrs: { disabled: true, class: 'gl-shadow-none! gl-text-secondary' },
|
||||
},
|
||||
i18n: {
|
||||
currentOrganization: s__('Organization|Current organization'),
|
||||
switchOrganizations: s__('Organization|Switch organizations'),
|
||||
},
|
||||
components: { GlDisclosureDropdown, GlAvatar, GlIcon, GlLoadingIcon },
|
||||
data() {
|
||||
return {
|
||||
organizations: {},
|
||||
dropdownShown: false,
|
||||
};
|
||||
},
|
||||
apollo: {
|
||||
organizations: {
|
||||
query: getCurrentUserOrganizations,
|
||||
update(data) {
|
||||
return data.currentUser.organizations;
|
||||
},
|
||||
skip() {
|
||||
return !this.dropdownShown;
|
||||
},
|
||||
error() {
|
||||
this.organizations = {
|
||||
nodes: [],
|
||||
pageInfo: {},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$apollo.queries.organizations.loading;
|
||||
},
|
||||
currentOrganization() {
|
||||
// TODO - use `gon.current_organization` when backend supports it.
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/437095
|
||||
return defaultOrganization;
|
||||
},
|
||||
nodes() {
|
||||
return this.organizations.nodes || [];
|
||||
},
|
||||
items() {
|
||||
const currentOrganizationGroup = {
|
||||
name: this.$options.i18n.currentOrganization,
|
||||
items: [
|
||||
{
|
||||
id: this.currentOrganization.id,
|
||||
text: this.currentOrganization.name,
|
||||
href: this.currentOrganization.web_url,
|
||||
avatarUrl: this.currentOrganization.avatar_url,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (this.loading || !this.dropdownShown) {
|
||||
return [
|
||||
currentOrganizationGroup,
|
||||
{
|
||||
name: this.$options.i18n.switchOrganizations,
|
||||
items: [this.$options.ITEM_LOADING],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const items = this.nodes
|
||||
.map((node) => ({
|
||||
id: getIdFromGraphQLId(node.id),
|
||||
text: node.name,
|
||||
href: node.webUrl,
|
||||
avatarUrl: node.avatarUrl,
|
||||
}))
|
||||
.filter((item) => item.id !== this.currentOrganization.id);
|
||||
|
||||
return [
|
||||
currentOrganizationGroup,
|
||||
{
|
||||
name: this.$options.i18n.switchOrganizations,
|
||||
items: items.length ? items : [this.$options.ITEM_EMPTY],
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onShown() {
|
||||
this.dropdownShown = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-disclosure-dropdown :items="items" class="gl-display-block" @shown="onShown">
|
||||
<template #toggle>
|
||||
<button
|
||||
class="organization-switcher-button gl-display-flex gl-align-items-center gl-gap-3 gl-p-3 gl-rounded-base gl-border-none gl-line-height-1 gl-w-full"
|
||||
data-testid="toggle-button"
|
||||
>
|
||||
<gl-avatar
|
||||
:size="24"
|
||||
:shape="$options.AVATAR_SHAPE_OPTION_RECT"
|
||||
:entity-id="currentOrganization.id"
|
||||
:entity-name="currentOrganization.name"
|
||||
:src="currentOrganization.avatar_url"
|
||||
/>
|
||||
<span>{{ currentOrganization.name }}</span>
|
||||
<gl-icon class="gl-button-icon gl-new-dropdown-chevron" name="chevron-down" />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<template #list-item="{ item }">
|
||||
<gl-loading-icon v-if="item.id === $options.ITEM_LOADING.id" />
|
||||
<span v-else-if="item.id === $options.ITEM_EMPTY.id">{{ item.text }}</span>
|
||||
<div v-else class="gl-display-flex gl-align-items-center gl-gap-3">
|
||||
<gl-avatar
|
||||
:size="24"
|
||||
:shape="$options.AVATAR_SHAPE_OPTION_RECT"
|
||||
:entity-id="item.id"
|
||||
:entity-name="item.text"
|
||||
:src="item.avatarUrl"
|
||||
/>
|
||||
<span>{{ item.text }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</gl-disclosure-dropdown>
|
||||
</template>
|
||||
|
|
@ -6,6 +6,7 @@ import {
|
|||
createUserCountsManager,
|
||||
userCounts,
|
||||
} from '~/super_sidebar/user_counts_manager';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import BrandLogo from 'jh_else_ce/super_sidebar/components/brand_logo.vue';
|
||||
import { JS_TOGGLE_COLLAPSE_CLASS } from '../constants';
|
||||
import CreateMenu from './create_menu.vue';
|
||||
|
|
@ -35,6 +36,8 @@ export default {
|
|||
SuperSidebarToggle,
|
||||
BrandLogo,
|
||||
GlIcon,
|
||||
OrganizationSwitcher: () =>
|
||||
import(/* webpackChunkName: 'organization_switcher' */ './organization_switcher.vue'),
|
||||
},
|
||||
i18n: {
|
||||
issues: __('Issues'),
|
||||
|
|
@ -52,6 +55,7 @@ export default {
|
|||
GlTooltip: GlTooltipDirective,
|
||||
GlModal: GlModalDirective,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
inject: ['isImpersonating'],
|
||||
props: {
|
||||
hasCollapseButton: {
|
||||
|
|
@ -149,6 +153,7 @@ export default {
|
|||
data-testid="stop-impersonation-btn"
|
||||
/>
|
||||
</div>
|
||||
<organization-switcher v-if="glFeatures.uiForOrganizations" />
|
||||
<div
|
||||
v-if="sidebarData.is_logged_in"
|
||||
class="gl-display-flex gl-justify-content-space-between gl-gap-2"
|
||||
|
|
|
|||
|
|
@ -231,6 +231,18 @@ $super-sidebar-transition-hint-duration: $super-sidebar-transition-duration / 4;
|
|||
.user-bar {
|
||||
background-color: var(--super-sidebar-user-bar-bg);
|
||||
|
||||
.organization-switcher-button {
|
||||
background-color: transparent;
|
||||
color: var(--super-sidebar-user-bar-button-color);
|
||||
|
||||
&:active,
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--super-sidebar-user-bar-button-hover-bg);
|
||||
color: var(--super-sidebar-user-bar-button-hover-color);
|
||||
}
|
||||
}
|
||||
|
||||
.user-bar-dropdown-toggle {
|
||||
padding: $gl-spacing-scale-2;
|
||||
@include gl-border-none;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ module Resolvers
|
|||
authorize :read_build
|
||||
|
||||
def resolve
|
||||
return unless Feature.enabled?(:sast_reports_in_inline_diff, object.project)
|
||||
|
||||
authorize!(object.actual_head_pipeline)
|
||||
|
||||
object.compare_codequality_reports
|
||||
|
|
|
|||
|
|
@ -237,17 +237,15 @@ module Types
|
|||
null: true,
|
||||
description: 'List of emoji reactions associated with the merge request.'
|
||||
|
||||
field :prepared_at, Types::TimeType, null: true,
|
||||
description: 'Timestamp of when the merge request was prepared.'
|
||||
|
||||
field :codequality_reports_comparer,
|
||||
type: ::Types::Security::CodequalityReportsComparerType,
|
||||
null: true,
|
||||
alpha: { milestone: '16.4' },
|
||||
description: 'Code quality reports comparison reported on the merge request. Returns `null` ' \
|
||||
'if `sast_reports_in_inline_diff` feature flag is disabled.',
|
||||
description: 'Code quality reports comparison reported on the merge request.',
|
||||
resolver: ::Resolvers::CodequalityReportsComparerResolver
|
||||
|
||||
field :prepared_at, Types::TimeType, null: true,
|
||||
description: 'Timestamp of when the merge request was prepared.'
|
||||
|
||||
field :allows_multiple_assignees,
|
||||
GraphQL::Types::Boolean,
|
||||
method: :allows_multiple_assignees?,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
class CodequalityDegradationEntity < Grape::Entity
|
||||
expose :description
|
||||
expose :fingerprint, if: ->(_, options) do
|
||||
Feature.enabled?(:sast_reports_in_inline_diff, options[:request]&.project)
|
||||
end
|
||||
expose :fingerprint
|
||||
expose :severity do |degradation|
|
||||
degradation.dig(:severity)&.downcase
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,11 +19,10 @@
|
|||
= render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :activate }), method: :put, button_options: { class: 'gl-display-none gl-md-display-inline-block' }) do
|
||||
= _('Reopen milestone')
|
||||
|
||||
.btn-group.gl-md-ml-3.gl-display-flex.dropdown.gl-dropdown.gl-md-w-auto.gl-w-full
|
||||
= button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret has-tooltip gl-display-none! gl-md-display-inline-flex!", data: { toggle: 'dropdown', title: _('Milestone actions'), testid: 'milestone-actions', 'aria-label': _('Milestone actions') }, aria: { label: _('Milestone actions') } do
|
||||
= sprite_icon "ellipsis_v", size: 16, css_class: "dropdown-icon gl-icon"
|
||||
= button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md btn-block gl-button gl-dropdown-toggle gl-md-display-none!", data: { 'toggle' => 'dropdown' } do
|
||||
%span.gl-dropdown-button-text= _('Milestone actions')
|
||||
.gl-md-ml-3.gl-display-flex.dropdown.gl-dropdown.gl-md-w-auto.gl-w-full
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary, icon: 'ellipsis_v', button_options: { class: 'has-tooltip gl-display-none! gl-md-display-inline-flex!', 'aria-label': _('Milestone actions'), data: { toggle: 'dropdown', title: _('Milestone actions'), testid: 'milestone-actions' } })
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'btn-block gl-md-display-none!', data: { toggle: 'dropdown' } }) do
|
||||
= _('Milestone actions')
|
||||
= sprite_icon "chevron-down", size: 16, css_class: "dropdown-icon gl-icon"
|
||||
.dropdown-menu.dropdown-menu-right
|
||||
.gl-dropdown-inner
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: prefix_scim_tokens
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139737
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/435423
|
||||
milestone: '16.8'
|
||||
type: development
|
||||
group: group::authentication
|
||||
default_enabled: false
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: sast_reports_in_inline_diff
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119975
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/410191
|
||||
milestone: '16.0'
|
||||
type: development
|
||||
group: group::static analysis
|
||||
default_enabled: true
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
- title: "Deprecate license metadata format V1"
|
||||
removal_milestone: "17.0"
|
||||
announcement_milestone: "16.9"
|
||||
breaking_change: true
|
||||
reporter: thiagocsf
|
||||
stage: Secure
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/438477
|
||||
body: | # (required) Don't change this line.
|
||||
The license metadata format V1 dataset has been deprecated and will be removed
|
||||
in GitLab 17.0.
|
||||
|
||||
Users who have the `package_metadata_synchronization` feature flag enabled are advised to
|
||||
upgrade to GitLab 16.3 or above, and remove the feature flag configuration.
|
||||
|
|
@ -16550,8 +16550,8 @@ Represents finding.
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="comparedsecurityreportfindingdescription"></a>`description` | [`String`](#string) | Description of the vulnerability finding. |
|
||||
| <a id="comparedsecurityreportfindingfoundbypipelineiid"></a>`foundByPipelineIid` | [`String`](#string) | IID of the pipeline. |
|
||||
| <a id="comparedsecurityreportfindingidentifiers"></a>`identifiers` **{warning-solid}** | [`[VulnerabilityIdentifier!]`](#vulnerabilityidentifier) | **Introduced** in 16.3. This feature is an Experiment. It can be changed or removed at any time. Identifiers of the vulnerability finding. Returns `null` if `sast_reports_in_inline_diff` feature flag is disabled. |
|
||||
| <a id="comparedsecurityreportfindinglocation"></a>`location` **{warning-solid}** | [`VulnerabilityLocation`](#vulnerabilitylocation) | **Introduced** in 16.3. This feature is an Experiment. It can be changed or removed at any time. Location of the vulnerability finding. Returns `null` if `sast_reports_in_inline_diff` feature flag is disabled. |
|
||||
| <a id="comparedsecurityreportfindingidentifiers"></a>`identifiers` **{warning-solid}** | [`[VulnerabilityIdentifier!]`](#vulnerabilityidentifier) | **Introduced** in 16.3. This feature is an Experiment. It can be changed or removed at any time. Identifiers of the vulnerability finding. |
|
||||
| <a id="comparedsecurityreportfindinglocation"></a>`location` **{warning-solid}** | [`VulnerabilityLocation`](#vulnerabilitylocation) | **Introduced** in 16.3. This feature is an Experiment. It can be changed or removed at any time. Location of the vulnerability finding. |
|
||||
| <a id="comparedsecurityreportfindingscanner"></a>`scanner` | [`ComparedSecurityReportScanner`](#comparedsecurityreportscanner) | Compared report vulnerability scanner. |
|
||||
| <a id="comparedsecurityreportfindingseverity"></a>`severity` | [`VulnerabilitySeverity`](#vulnerabilityseverity) | Severity of the vulnerability finding. |
|
||||
| <a id="comparedsecurityreportfindingstate"></a>`state` | [`VulnerabilityState`](#vulnerabilitystate) | Finding status. |
|
||||
|
|
@ -21598,7 +21598,7 @@ Defines which user roles, users, or groups can merge into a protected branch.
|
|||
| <a id="mergerequestavailableautomergestrategies"></a>`availableAutoMergeStrategies` | [`[String!]`](#string) | Array of available auto merge strategies. |
|
||||
| <a id="mergerequestawardemoji"></a>`awardEmoji` | [`AwardEmojiConnection`](#awardemojiconnection) | List of emoji reactions associated with the merge request. (see [Connections](#connections)) |
|
||||
| <a id="mergerequestblockingmergerequests"></a>`blockingMergeRequests` **{warning-solid}** | [`BlockingMergeRequests`](#blockingmergerequests) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Merge requests that block another merge request from merging. |
|
||||
| <a id="mergerequestcodequalityreportscomparer"></a>`codequalityReportsComparer` **{warning-solid}** | [`CodequalityReportsComparer`](#codequalityreportscomparer) | **Introduced** in 16.4. This feature is an Experiment. It can be changed or removed at any time. Code quality reports comparison reported on the merge request. Returns `null` if `sast_reports_in_inline_diff` feature flag is disabled. |
|
||||
| <a id="mergerequestcodequalityreportscomparer"></a>`codequalityReportsComparer` | [`CodequalityReportsComparer`](#codequalityreportscomparer) | Code quality reports comparison reported on the merge request. |
|
||||
| <a id="mergerequestcommenters"></a>`commenters` | [`UserCoreConnection!`](#usercoreconnection) | All commenters on this noteable. (see [Connections](#connections)) |
|
||||
| <a id="mergerequestcommitcount"></a>`commitCount` | [`Int`](#int) | Number of commits in the merge request. |
|
||||
| <a id="mergerequestcommits"></a>`commits` | [`CommitConnection`](#commitconnection) | Merge request commits. (see [Connections](#connections)) |
|
||||
|
|
|
|||
|
|
@ -804,6 +804,12 @@ With multi-project pipelines, the trigger job fails and does not create the down
|
|||
to run pipelines against the protected branch. See [pipeline security for protected branches](index.md#pipeline-security-on-protected-branches)
|
||||
for more information.
|
||||
|
||||
To identify which user is having permission issues in the downstream project, you can check the trigger job using the following command in the [Rails console](../../administration/operations/rails_console.md) and look at the `user_id` attribute.
|
||||
|
||||
```ruby
|
||||
Ci::Bridge.find(<job_id>)
|
||||
```
|
||||
|
||||
### Job in child pipeline is not created when the pipeline runs
|
||||
|
||||
If the parent pipeline is a [merge request pipeline](merge_request_pipelines.md),
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ features is limited by our linters, so, use regular Markdown and follow the rule
|
|||
linked style guide. You can't use Kramdown-specific markup (for example, `{:.class}`).
|
||||
|
||||
For a complete Kramdown reference, see the
|
||||
[GitLab Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
|
||||
[GitLab Markdown Guide](https://handbook.gitlab.com/handbook/markdown-guide/).
|
||||
|
||||
The Markdown format is [tested](../testing.md) by using markdownlint and Vale.
|
||||
|
||||
|
|
|
|||
|
|
@ -115,13 +115,13 @@ To deprecate a page or topic:
|
|||
|
||||
WARNING:
|
||||
This feature was [deprecated](<link-to-issue>) in GitLab 14.8
|
||||
and is planned for removal in 15.4. Use [feature X](<link-to-issue>) instead.
|
||||
and is planned for removal in 15.4. Use [feature X](<link-to-docs>) instead.
|
||||
```
|
||||
|
||||
If you're not sure when the feature will be removed or no
|
||||
replacement feature exists, you don't need to add this information.
|
||||
|
||||
1. If the deprecation is a breaking change, add this text:
|
||||
1. If the deprecation is a [breaking change](../../update/terminology.md#breaking-change), add this text:
|
||||
|
||||
```markdown
|
||||
This change is a breaking change.
|
||||
|
|
@ -139,7 +139,7 @@ To deprecate a page or topic:
|
|||
|
||||
WARNING:
|
||||
This feature was [deprecated](<link-to-issue>) in GitLab 14.8
|
||||
and is planned for removal in 15.4. Use [feature X](<link-to-issue>) instead.
|
||||
and is planned for removal in 15.4. Use [feature X](<link-to-docs>) instead.
|
||||
|
||||
<!--- end_remove -->
|
||||
```
|
||||
|
|
@ -174,7 +174,7 @@ To remove a page:
|
|||
|
||||
This feature was [deprecated](<link-to-issue>) in GitLab X.Y
|
||||
and [removed](<link-to-issue>) in X.Y.
|
||||
Use [feature X](<link-to-issue>) instead.
|
||||
Use [feature X](<link-to-docs>) instead.
|
||||
```
|
||||
|
||||
1. Remove the page's entry from the global navigation by editing [`navigation.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/content/_data/navigation.yaml) in `gitlab-docs`.
|
||||
|
|
@ -199,7 +199,7 @@ To remove a topic:
|
|||
|
||||
This feature was [deprecated](<link-to-issue>) in GitLab X.Y
|
||||
and [removed](<link-to-issue>) in X.Y.
|
||||
Use [feature X](<link-to-issue>) instead.
|
||||
Use [feature X](<link-to-docs>) instead.
|
||||
|
||||
<!--- end_remove -->
|
||||
```
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ The following tables show the prefixes for each type of token where applicable.
|
|||
| Incoming mail token | `glimt-` |
|
||||
| GitLab Agent for Kubernetes token | `glagent-` |
|
||||
| GitLab session cookies | `_gitlab_session=` |
|
||||
| SCIM Tokens | `glsoat-` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435096) in GitLab 16.8 behind a feature flag named `prefix_scim_tokens`. Disabled by default.) |
|
||||
| SCIM Tokens | `glsoat-` <br /> • ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435096) in GitLab 16.8 behind a feature flag named `prefix_scim_tokens`. Disabled by default.) <br > • ([Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/435423) in GitLab 16.9. Feature flag `prefix_scim_tokens` removed.) |
|
||||
|
||||
### External system tokens
|
||||
|
||||
|
|
|
|||
|
|
@ -575,6 +575,24 @@ The runner's legacy escape sequence mechanism to handle variable expansion imple
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Deprecate license metadata format V1
|
||||
|
||||
<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/-/issues/438477).
|
||||
</div>
|
||||
|
||||
The license metadata format V1 dataset has been deprecated and will be removed
|
||||
in GitLab 17.0.
|
||||
|
||||
Users who have the `package_metadata_synchronization` feature flag enabled are advised to
|
||||
upgrade to GitLab 16.3 or above, and remove the feature flag configuration.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Deprecated parameters related to custom text in the sign-in page
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ were introduced by the changes made in the merge request.
|
|||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/10959) in GitLab 16.6 with a [flag](../../../administration/feature_flags.md) named `sast_reports_in_inline_diff`. Disabled by default.
|
||||
> - Enabled by default in GitLab 16.8.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/410191) in GitLab 16.9.
|
||||
|
||||
SAST results display in the merge request **Changes** view. Lines containing SAST
|
||||
issues are marked by a symbol beside the gutter. Select the symbol to see the list of issues, then select an issue to see its details.
|
||||
|
|
|
|||
|
|
@ -52,14 +52,19 @@ Prerequisites:
|
|||
|
||||
- You must have a role in the project that allows you to edit merge requests, and add
|
||||
code to the repository.
|
||||
- The commit must not have already been reverted, as the **Revert** option is not
|
||||
shown in this case.
|
||||
|
||||
To do this:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. If you know the merge request that contains the commit:
|
||||
1. Select **Code > Merge requests**, then identify and select your merge request.
|
||||
1. Select **Commits**, then select the title of the commit you want to revert. This displays the commit in the **Changes** tab of your merge request.
|
||||
1. Select the commit hash you want to revert. GitLab displays the contents of the commit.
|
||||
1. Select **Code > Merge requests**, then select your merge request.
|
||||
1. Select **Commits**, then select the title of the commit you want to revert.
|
||||
This displays the commit in the context of your merge request.
|
||||
1. Below the secondary menu, the message **Viewing commit `00001111`** is shown,
|
||||
where `00001111` is the hash of the commit. Select the commit hash to show
|
||||
the commit's page.
|
||||
1. If you don't know the merge request the commit originated from:
|
||||
1. Select **Code > Commits**.
|
||||
1. Select the title of the commit to display full information about the commit.
|
||||
|
|
@ -68,8 +73,6 @@ To do this:
|
|||
1. Optional. Select **Start a new merge request** to start a new merge request with the new revert commit.
|
||||
1. Select **Revert**.
|
||||
|
||||
The option to **Revert** is no longer shown after a commit is reverted.
|
||||
|
||||
### Revert a merge commit to a different parent commit
|
||||
|
||||
When you revert a merge commit, the branch you merged to (usually `main`) is always the
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ module Gitlab
|
|||
push_frontend_feature_flag(:source_editor_toolbar)
|
||||
push_frontend_feature_flag(:vscode_web_ide, current_user)
|
||||
push_frontend_feature_flag(:key_contacts_management, current_user)
|
||||
push_frontend_feature_flag(:ui_for_organizations, current_user)
|
||||
# To be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/399248
|
||||
push_frontend_feature_flag(:remove_monitor_metrics)
|
||||
push_frontend_feature_flag(:custom_emoji)
|
||||
|
|
|
|||
|
|
@ -34232,6 +34232,9 @@ msgstr ""
|
|||
msgid "Organization|Create organization"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Current organization"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Frequently visited groups"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -34256,6 +34259,9 @@ msgstr ""
|
|||
msgid "Organization|New organization"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|No organizations available to switch to."
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Org ID"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -34319,6 +34325,9 @@ msgstr ""
|
|||
msgid "Organization|Select an organization"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Switch organizations"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Unable to fetch organizations. Reload the page to try again."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ RSpec.describe 'Navigation menu item pinning', :js, feature_category: :navigatio
|
|||
|
||||
def add_pin(nav_item_title)
|
||||
nav_item = find("[data-testid=\"nav-item\"]", text: nav_item_title)
|
||||
scroll_to(nav_item)
|
||||
nav_item.hover
|
||||
pin_button = nav_item.find("[data-testid=\"nav-item-pin\"]")
|
||||
pin_button.click
|
||||
|
|
@ -178,6 +179,7 @@ RSpec.describe 'Navigation menu item pinning', :js, feature_category: :navigatio
|
|||
|
||||
def remove_pin(nav_item_title)
|
||||
nav_item = find("[data-testid=\"nav-item\"]", text: nav_item_title)
|
||||
scroll_to(nav_item)
|
||||
nav_item.hover
|
||||
unpin_button = nav_item.find("[data-testid=\"nav-item-unpin\"]")
|
||||
unpin_button.click
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
import { GlAvatar, GlDisclosureDropdown, GlLoadingIcon } from '@gitlab/ui';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import Vue from 'vue';
|
||||
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import OrganizationSwitcher from '~/super_sidebar/components/organization_switcher.vue';
|
||||
import {
|
||||
defaultOrganization as currentOrganization,
|
||||
organizations as nodes,
|
||||
pageInfo,
|
||||
pageInfoEmpty,
|
||||
} from '~/organizations/mock_data';
|
||||
import organizationsQuery from '~/organizations/shared/graphql/queries/organizations.query.graphql';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
describe('OrganizationSwitcher', () => {
|
||||
let wrapper;
|
||||
let mockApollo;
|
||||
|
||||
const [, secondOrganization, thirdOrganization] = nodes;
|
||||
|
||||
const organizations = {
|
||||
nodes,
|
||||
pageInfo,
|
||||
};
|
||||
|
||||
const successHandler = jest.fn().mockResolvedValue({
|
||||
data: {
|
||||
currentUser: {
|
||||
id: 'gid://gitlab/User/1',
|
||||
organizations,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const createComponent = (handler = successHandler) => {
|
||||
mockApollo = createMockApollo([[organizationsQuery, handler]]);
|
||||
|
||||
wrapper = mountExtended(OrganizationSwitcher, {
|
||||
apolloProvider: mockApollo,
|
||||
});
|
||||
};
|
||||
|
||||
const findDropdownItemByIndex = (index) =>
|
||||
wrapper.findAllByTestId('disclosure-dropdown-item').at(index);
|
||||
const showDropdown = () => wrapper.findComponent(GlDisclosureDropdown).vm.$emit('shown');
|
||||
|
||||
afterEach(() => {
|
||||
mockApollo = null;
|
||||
});
|
||||
|
||||
it('renders disclosure dropdown with current organization selected', () => {
|
||||
createComponent();
|
||||
|
||||
const toggleButton = wrapper.findByTestId('toggle-button');
|
||||
const dropdownItem = findDropdownItemByIndex(0);
|
||||
|
||||
expect(toggleButton.text()).toContain(currentOrganization.name);
|
||||
expect(toggleButton.findComponent(GlAvatar).props()).toMatchObject({
|
||||
src: currentOrganization.avatar_url,
|
||||
entityId: currentOrganization.id,
|
||||
entityName: currentOrganization.name,
|
||||
});
|
||||
expect(dropdownItem.text()).toContain(currentOrganization.name);
|
||||
expect(dropdownItem.findComponent(GlAvatar).props()).toMatchObject({
|
||||
src: currentOrganization.avatar_url,
|
||||
entityId: currentOrganization.id,
|
||||
entityName: currentOrganization.name,
|
||||
});
|
||||
});
|
||||
|
||||
it('does not call GraphQL query', () => {
|
||||
createComponent();
|
||||
|
||||
expect(successHandler).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when dropdown is shown', () => {
|
||||
it('calls GraphQL query and renders organizations that are available to switch to', async () => {
|
||||
createComponent();
|
||||
showDropdown();
|
||||
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(findDropdownItemByIndex(1).text()).toContain(secondOrganization.name);
|
||||
expect(findDropdownItemByIndex(1).element.firstChild.getAttribute('href')).toBe(
|
||||
secondOrganization.webUrl,
|
||||
);
|
||||
expect(findDropdownItemByIndex(1).findComponent(GlAvatar).props()).toMatchObject({
|
||||
src: secondOrganization.avatarUrl,
|
||||
entityId: getIdFromGraphQLId(secondOrganization.id),
|
||||
entityName: secondOrganization.name,
|
||||
});
|
||||
|
||||
expect(findDropdownItemByIndex(2).text()).toContain(thirdOrganization.name);
|
||||
expect(findDropdownItemByIndex(2).element.firstChild.getAttribute('href')).toBe(
|
||||
thirdOrganization.webUrl,
|
||||
);
|
||||
expect(findDropdownItemByIndex(2).findComponent(GlAvatar).props()).toMatchObject({
|
||||
src: thirdOrganization.avatarUrl,
|
||||
entityId: getIdFromGraphQLId(thirdOrganization.id),
|
||||
entityName: thirdOrganization.name,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there are no organizations to switch to', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent(
|
||||
jest.fn().mockResolvedValue({
|
||||
data: {
|
||||
currentUser: {
|
||||
id: 'gid://gitlab/User/1',
|
||||
organizations: {
|
||||
nodes: [],
|
||||
pageInfo: pageInfoEmpty,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
showDropdown();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('renders empty message', () => {
|
||||
expect(findDropdownItemByIndex(1).text()).toBe('No organizations available to switch to.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there is an error fetching organizations', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent(jest.fn().mockRejectedValue());
|
||||
showDropdown();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('renders empty message', () => {
|
||||
expect(findDropdownItemByIndex(1).text()).toBe('No organizations available to switch to.');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -9,16 +9,20 @@ import UserMenu from '~/super_sidebar/components/user_menu.vue';
|
|||
import SearchModal from '~/super_sidebar/components/global_search/components/global_search.vue';
|
||||
import BrandLogo from 'jh_else_ce/super_sidebar/components/brand_logo.vue';
|
||||
import MergeRequestMenu from '~/super_sidebar/components/merge_request_menu.vue';
|
||||
import OrganizationSwitcher from '~/super_sidebar/components/organization_switcher.vue';
|
||||
import UserBar from '~/super_sidebar/components/user_bar.vue';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { userCounts } from '~/super_sidebar/user_counts_manager';
|
||||
import { stubComponent } from 'helpers/stub_component';
|
||||
import { sidebarData as mockSidebarData, loggedOutSidebarData } from '../mock_data';
|
||||
import { MOCK_DEFAULT_SEARCH_OPTIONS } from './global_search/mock_data';
|
||||
|
||||
describe('UserBar component', () => {
|
||||
let wrapper;
|
||||
|
||||
const OrganizationSwitcherStub = stubComponent(OrganizationSwitcher);
|
||||
|
||||
const findCreateMenu = () => wrapper.findComponent(CreateMenu);
|
||||
const findUserMenu = () => wrapper.findComponent(UserMenu);
|
||||
const findIssuesCounter = () => wrapper.findByTestId('issues-shortcut-button');
|
||||
|
|
@ -30,6 +34,7 @@ describe('UserBar component', () => {
|
|||
const findSearchButton = () => wrapper.findByTestId('super-sidebar-search-button');
|
||||
const findSearchModal = () => wrapper.findComponent(SearchModal);
|
||||
const findStopImpersonationButton = () => wrapper.findByTestId('stop-impersonation-btn');
|
||||
const findOrganizationSwitcher = () => wrapper.findComponent(OrganizationSwitcherStub);
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
|
|
@ -56,6 +61,9 @@ describe('UserBar component', () => {
|
|||
GlTooltip: createMockDirective('gl-tooltip'),
|
||||
},
|
||||
store,
|
||||
stubs: {
|
||||
OrganizationSwitcher: OrganizationSwitcherStub,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -252,4 +260,22 @@ describe('UserBar component', () => {
|
|||
expect(findTodosCounter().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `ui_for_organizations` feature flag is enabled', () => {
|
||||
it('renders `OrganizationSwitcher component', async () => {
|
||||
createWrapper({ provideOverrides: { glFeatures: { uiForOrganizations: true } } });
|
||||
await waitForPromises();
|
||||
|
||||
expect(findOrganizationSwitcher().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `ui_for_organizations` feature flag is disabled', () => {
|
||||
it('renders `OrganizationSwitcher component', async () => {
|
||||
createWrapper();
|
||||
await waitForPromises();
|
||||
|
||||
expect(findOrganizationSwitcher().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -125,16 +125,6 @@ RSpec.describe 'Query.project.mergeRequest.codequalityReportsComparer', feature_
|
|||
post_graphql(query, current_user: user)
|
||||
end
|
||||
|
||||
context 'when when sast_reports_in_inline_diff FF is disabled' do
|
||||
before_all do
|
||||
stub_feature_flags(sast_reports_in_inline_diff: false)
|
||||
end
|
||||
|
||||
it 'returns null for codequality_reports_comparer field' do
|
||||
expect(result).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns expected data' do
|
||||
expect(result).to match(
|
||||
a_hash_including(
|
||||
|
|
|
|||
|
|
@ -8,18 +8,6 @@ RSpec.describe CodequalityDegradationEntity, feature_category: :code_quality do
|
|||
describe '#as_json' do
|
||||
subject { entity.as_json }
|
||||
|
||||
context 'when sast_reports_in_inline_diff is disabled' do
|
||||
before do
|
||||
stub_feature_flags(sast_reports_in_inline_diff: false)
|
||||
end
|
||||
|
||||
let(:codequality_degradation) { build(:codequality_degradation_1) }
|
||||
|
||||
it 'does not contain fingerprint' do
|
||||
expect(subject[:fingerprint]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when codequality contains an error' do
|
||||
context 'when line is included in location' do
|
||||
let(:codequality_degradation) { build(:codequality_degradation_2) }
|
||||
|
|
|
|||
Loading…
Reference in New Issue