Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f3a2d44292
commit
948b3c5ace
|
|
@ -1044,6 +1044,8 @@
|
|||
- <<: *if-merge-request-labels-pipeline-expedite
|
||||
when: never
|
||||
- if: '$ENABLE_BUILD_ASSETS_IMAGE == "true"'
|
||||
- !reference [".release-environments:rules:start-release-environments-pipeline", rules]
|
||||
- !reference [".release-environments:rules:start-release-environments-security-pipeline", rules]
|
||||
- !reference [".frontend:rules:assets-shared", rules]
|
||||
|
||||
.build-images:rules:build-assets-image-as-if-foss:
|
||||
|
|
|
|||
|
|
@ -45,12 +45,6 @@ Rails/OutputSafety:
|
|||
- 'app/helpers/whats_new_helper.rb'
|
||||
- 'app/mailers/notify.rb'
|
||||
- 'app/models/concerns/restricted_signup.rb'
|
||||
- 'app/models/integrations/apple_app_store.rb'
|
||||
- 'app/models/integrations/confluence.rb'
|
||||
- 'app/models/integrations/datadog.rb'
|
||||
- 'app/models/integrations/discord.rb'
|
||||
- 'app/models/integrations/google_play.rb'
|
||||
- 'app/models/integrations/hangouts_chat.rb'
|
||||
- 'app/presenters/ci/pipeline_presenter.rb'
|
||||
- 'app/presenters/key_presenter.rb'
|
||||
- 'app/presenters/project_presenter.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
7472acfcaa3ee8406581e33a54c9949daef1a22e
|
||||
0b93282f3ccd586a8916a0eddc3bc3b955654cc1
|
||||
|
|
|
|||
|
|
@ -1,15 +1,8 @@
|
|||
<script>
|
||||
import {
|
||||
GlCard,
|
||||
GlTable,
|
||||
GlButton,
|
||||
GlIcon,
|
||||
GlModal,
|
||||
GlModalDirective,
|
||||
GlSprintf,
|
||||
} from '@gitlab/ui';
|
||||
import { GlTable, GlButton, GlModal, GlModalDirective, GlSprintf } from '@gitlab/ui';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { mapState, mapActions } from 'vuex';
|
||||
import CrudComponent from '~/vue_shared/components/crud_component.vue';
|
||||
import { __, s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
|
|
@ -58,10 +51,9 @@ export default {
|
|||
},
|
||||
},
|
||||
components: {
|
||||
GlCard,
|
||||
CrudComponent,
|
||||
GlTable,
|
||||
GlButton,
|
||||
GlIcon,
|
||||
GlModal,
|
||||
GlSprintf,
|
||||
},
|
||||
|
|
@ -96,24 +88,16 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<gl-card
|
||||
class="gl-new-card deploy-freeze-table"
|
||||
header-class="gl-new-card-header"
|
||||
body-class="gl-new-card-body gl-px-0"
|
||||
<crud-component
|
||||
class="deploy-freeze-table"
|
||||
:title="$options.i18n.title"
|
||||
icon="deployments"
|
||||
:count="freezePeriods.length"
|
||||
>
|
||||
<template #header>
|
||||
<div class="gl-new-card-title-wrapper">
|
||||
<h3 class="gl-new-card-title">{{ $options.i18n.title }}</h3>
|
||||
<span class="gl-new-card-count">
|
||||
<gl-icon name="deployments" class="gl-mr-2" />
|
||||
{{ freezePeriods.length }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="gl-new-card-actions">
|
||||
<gl-button v-gl-modal.deploy-freeze-modal size="small" data-testid="add-deploy-freeze">{{
|
||||
$options.i18n.addDeployFreeze
|
||||
}}</gl-button>
|
||||
</div>
|
||||
<template #actions>
|
||||
<gl-button v-gl-modal.deploy-freeze-modal size="small" data-testid="add-deploy-freeze">{{
|
||||
$options.i18n.addDeployFreeze
|
||||
}}</gl-button>
|
||||
</template>
|
||||
|
||||
<gl-table
|
||||
|
|
@ -127,19 +111,18 @@ export default {
|
|||
{{ item.cronTimezone.formattedTimezone }}
|
||||
</template>
|
||||
<template #cell(actions)="{ item }">
|
||||
<div class="gl-display-flex gl-justify-content-end -gl-mt-2 -gl-mb-2">
|
||||
<div class="gl-flex gl-justify-end gl-gap-2 -gl-mt-2 -gl-mb-2">
|
||||
<gl-button
|
||||
v-gl-modal.deploy-freeze-modal
|
||||
icon="pencil"
|
||||
category="tertiary"
|
||||
data-testid="edit-deploy-freeze"
|
||||
:aria-label="__('Edit deploy freeze')"
|
||||
class="gl-mr-3"
|
||||
@click="setFreezePeriod(item)"
|
||||
/>
|
||||
<gl-button
|
||||
v-gl-modal="$options.modal.id"
|
||||
category="secondary"
|
||||
variant="danger"
|
||||
category="tertiary"
|
||||
icon="remove"
|
||||
:aria-label="$options.modal.actionPrimary.text"
|
||||
:loading="item.isDeleting"
|
||||
|
|
@ -149,7 +132,7 @@ export default {
|
|||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<p data-testid="empty-freeze-periods" class="gl-text-secondary gl-text-center gl-mb-0">
|
||||
<p data-testid="empty-freeze-periods" class="gl-text-subtle gl-text-center gl-mb-0">
|
||||
<gl-sprintf :message="$options.i18n.emptyStateText">
|
||||
<template #strong="{ content }">
|
||||
{{ content }}
|
||||
|
|
@ -178,5 +161,5 @@ export default {
|
|||
</gl-sprintf>
|
||||
</template>
|
||||
</gl-modal>
|
||||
</gl-card>
|
||||
</crud-component>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ export default {
|
|||
default: null,
|
||||
},
|
||||
count: {
|
||||
type: Number,
|
||||
type: [String, Number],
|
||||
required: false,
|
||||
default: null,
|
||||
default: '',
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
|
|
|
|||
|
|
@ -747,7 +747,7 @@ class Integration < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
def self.build_help_page_url(url_path, help_text, options = {})
|
||||
def self.build_help_page_url(url_path, help_text, link_text = _("Learn More"), options = {})
|
||||
docs_link = ActionController::Base.helpers.link_to(
|
||||
'',
|
||||
Rails.application.routes.url_helpers.help_page_url(url_path, **options),
|
||||
|
|
@ -756,7 +756,7 @@ class Integration < ApplicationRecord
|
|||
)
|
||||
tag_pair_docs_link = tag_pair(docs_link, :link_start, :link_end)
|
||||
|
||||
safe_format(help_text + s_(" %{link_start}Learn More%{link_end}."), tag_pair_docs_link)
|
||||
safe_format(help_text + " %{link_start}#{link_text}%{link_end}.", tag_pair_docs_link)
|
||||
end
|
||||
|
||||
# Ancestors sorted by hierarchy depth in bottom-top order.
|
||||
|
|
|
|||
|
|
@ -57,22 +57,28 @@ module Integrations
|
|||
|
||||
def self.help
|
||||
variable_list = [
|
||||
'<code>APP_STORE_CONNECT_API_KEY_ISSUER_ID</code>',
|
||||
'<code>APP_STORE_CONNECT_API_KEY_KEY_ID</code>',
|
||||
'<code>APP_STORE_CONNECT_API_KEY_KEY</code>',
|
||||
'<code>APP_STORE_CONNECT_API_KEY_IS_KEY_CONTENT_BASE64</code>'
|
||||
ActionController::Base.helpers.content_tag(:code, 'APP_STORE_CONNECT_API_KEY_ISSUER_ID'),
|
||||
ActionController::Base.helpers.content_tag(:code, 'APP_STORE_CONNECT_API_KEY_KEY_ID'),
|
||||
ActionController::Base.helpers.content_tag(:code, 'APP_STORE_CONNECT_API_KEY_KEY'),
|
||||
ActionController::Base.helpers.content_tag(:code, 'APP_STORE_CONNECT_API_KEY_IS_KEY_CONTENT_BASE64')
|
||||
]
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
docs_link = ActionController::Base.helpers.link_to(
|
||||
'',
|
||||
Rails.application.routes.url_helpers.help_page_url('user/project/integrations/apple_app_store'),
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer'
|
||||
)
|
||||
tag_pair_docs_link = tag_pair(docs_link, :link_start, :link_end)
|
||||
|
||||
texts = [
|
||||
s_("Use this integration to connect to the Apple App Store with fastlane in CI/CD pipelines."),
|
||||
s_("After you enable the integration, the following protected variables are created for CI/CD use:"),
|
||||
variable_list.join('<br>'),
|
||||
s_(format("For more information, see the <a href='%{url}' target='_blank'>documentation</a>.", url: Rails.application.routes.url_helpers.help_page_url('user/project/integrations/apple_app_store'))).html_safe
|
||||
ActionController::Base.helpers.safe_join(variable_list, ActionController::Base.helpers.tag(:br)),
|
||||
safe_format(s_("For more information, see the %{link_start}documentation%{link_end}."), tag_pair_docs_link)
|
||||
]
|
||||
# rubocop:enable Layout/LineLength
|
||||
|
||||
texts.join('<br><br>'.html_safe)
|
||||
ActionController::Base.helpers.safe_join(texts, ActionController::Base.helpers.tag(:br) * 2)
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
module Integrations
|
||||
class BaseThirdPartyWiki < Integration
|
||||
include SafeFormatHelper
|
||||
|
||||
attribute :category, default: 'third_party_wiki'
|
||||
|
||||
validate :only_one_third_party_wiki, if: :activated?, on: :manual_change
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ module Integrations
|
|||
if activated?
|
||||
wiki_url = project.wiki.web_url
|
||||
|
||||
s_(
|
||||
'ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To re-enable the link to the GitLab wiki, disable this integration.' %
|
||||
{ wiki_link: ActionController::Base.helpers.link_to(wiki_url, wiki_url) }
|
||||
).html_safe
|
||||
docs_link = ActionController::Base.helpers.link_to('', wiki_url, target: '_blank', rel: 'noopener noreferrer')
|
||||
tag_pair_docs_link = tag_pair(docs_link, :link_start, :link_end)
|
||||
|
||||
safe_format(s_("'ConfluenceService|Your GitLab wiki is still available at %{link_start}#{wiki_url}%{link_end}. To re-enable the link to the GitLab wiki, disable this integration."), tag_pair_docs_link)
|
||||
else
|
||||
s_('ConfluenceService|Link to a Confluence Workspace from the sidebar. Enabling this integration replaces the "Wiki" sidebar link with a link to the Confluence Workspace. The GitLab wiki is still available at the original URL.').html_safe
|
||||
s_('ConfluenceService|Link to a Confluence Workspace from the sidebar. Enabling this integration replaces the "Wiki" sidebar link with a link to the Confluence Workspace. The GitLab wiki is still available at the original URL.')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -37,12 +37,10 @@ module Integrations
|
|||
non_empty_password_title: -> { s_('ProjectService|Enter new API key') },
|
||||
non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current API key') },
|
||||
help: -> do
|
||||
ERB::Util.html_escape(
|
||||
s_('DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog.')
|
||||
) % {
|
||||
linkOpen: %(<a href="#{URL_API_KEYS_DOCS}" target="_blank" rel="noopener noreferrer">).html_safe,
|
||||
linkClose: '</a>'.html_safe
|
||||
}
|
||||
docs_link = ActionController::Base.helpers.link_to('', URL_API_KEYS_DOCS, target: '_blank', rel: 'noopener noreferrer')
|
||||
tag_pair_docs_link = tag_pair(docs_link, :link_start, :link_end)
|
||||
|
||||
safe_format(s_('DatadogIntegration|%{link_start}API key%{link_end} used for authentication with Datadog.'), tag_pair_docs_link)
|
||||
end,
|
||||
required: true
|
||||
|
||||
|
|
@ -126,12 +124,11 @@ module Integrations
|
|||
end
|
||||
|
||||
def self.help
|
||||
docs_link = ActionController::Base.helpers.link_to(
|
||||
s_('DatadogIntegration|How do I set up this integration?'),
|
||||
Rails.application.routes.url_helpers.help_page_url('integration/datadog'),
|
||||
target: '_blank', rel: 'noopener noreferrer'
|
||||
build_help_page_url(
|
||||
'integration/datadog',
|
||||
s_('DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues.'),
|
||||
_('How do I set up this integration?')
|
||||
)
|
||||
s_('DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
|
|
|
|||
|
|
@ -33,8 +33,11 @@ module Integrations
|
|||
end
|
||||
|
||||
def self.help
|
||||
docs_link = ActionController::Base.helpers.link_to _('How do I set up this service?'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/discord_notifications'), target: '_blank', rel: 'noopener noreferrer'
|
||||
s_('Send notifications about project events to a Discord channel. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
|
||||
build_help_page_url(
|
||||
'user/project/integrations/discord_notifications',
|
||||
s_("DiscordService|Send notifications about project events to a Discord channel."),
|
||||
_('How do I set up this integration?')
|
||||
)
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
|
|
|
|||
|
|
@ -48,20 +48,26 @@ module Integrations
|
|||
|
||||
def self.help
|
||||
variable_list = [
|
||||
'<code>SUPPLY_PACKAGE_NAME</code>',
|
||||
'<code>SUPPLY_JSON_KEY_DATA</code>'
|
||||
ActionController::Base.helpers.content_tag(:code, "SUPPLY_PACKAGE_NAME"),
|
||||
ActionController::Base.helpers.content_tag(:code, "SUPPLY_JSON_KEY_DATA")
|
||||
]
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
docs_link = ActionController::Base.helpers.link_to(
|
||||
'',
|
||||
Rails.application.routes.url_helpers.help_page_url('user/project/integrations/google_play'),
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer'
|
||||
)
|
||||
tag_pair_docs_link = tag_pair(docs_link, :link_start, :link_end)
|
||||
|
||||
texts = [
|
||||
s_("Use this integration to connect to Google Play with fastlane in CI/CD pipelines."),
|
||||
s_("After you enable the integration, the following protected variables are created for CI/CD use:"),
|
||||
variable_list.join('<br>'),
|
||||
s_(format("For more information, see the <a href='%{url}' target='_blank'>documentation</a>.", url: Rails.application.routes.url_helpers.help_page_url('user/project/integrations/google_play'))).html_safe
|
||||
ActionController::Base.helpers.safe_join(variable_list, ActionController::Base.helpers.tag(:br)),
|
||||
safe_format(s_("For more information, see the %{link_start}documentation%{link_end}."), tag_pair_docs_link)
|
||||
]
|
||||
# rubocop:enable Layout/LineLength
|
||||
|
||||
texts.join('<br><br>'.html_safe)
|
||||
ActionController::Base.helpers.safe_join(texts, ActionController::Base.helpers.tag(:br) * 2)
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
|
|
|
|||
|
|
@ -35,12 +35,12 @@ module Integrations
|
|||
end
|
||||
|
||||
def self.help
|
||||
docs_link = ActionController::Base.helpers.link_to(_('How do I set up a Google Chat webhook?'),
|
||||
Rails.application.routes.url_helpers.help_page_url('user/project/integrations/hangouts_chat'),
|
||||
target: '_blank', rel: 'noopener noreferrer')
|
||||
format(
|
||||
s_('Before enabling this integration, create a webhook for the space in Google Chat where you want to ' \
|
||||
'receive notifications from this project. %{docs_link}').html_safe, docs_link: docs_link.html_safe)
|
||||
build_help_page_url(
|
||||
'user/project/integrations/hangouts_chat',
|
||||
'Before enabling this integration, create a webhook for the space in Google Chat where you want to ' \
|
||||
'receive notifications from this project.',
|
||||
_('How do I set up a Google Chat webhook?')
|
||||
)
|
||||
end
|
||||
|
||||
def default_channel_placeholder; end
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ feature_categories:
|
|||
description: Stores version information for software components produced by a Software Bill of Materials (SBoM)
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90809
|
||||
milestone: '15.2'
|
||||
gitlab_schema: gitlab_main
|
||||
gitlab_schema: gitlab_sec
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/457096
|
||||
|
|
|
|||
|
|
@ -844,6 +844,9 @@ really fast because:
|
|||
- GitLab Shell and Gitaly setup are skipped
|
||||
- Test repositories setup are skipped
|
||||
|
||||
It takes around one second to load tests that are using `fast_spec_helper`
|
||||
instead of 30+ seconds in case of a regular `spec_helper`.
|
||||
|
||||
`fast_spec_helper` also support autoloading classes that are located inside the
|
||||
`lib/` directory. If your class or module is using only
|
||||
code from the `lib/` directory, you don't need to explicitly load any
|
||||
|
|
@ -861,10 +864,15 @@ should either:
|
|||
- Add `require_dependency 're2'` to files in your library that need `re2` gem,
|
||||
to make this requirement explicit. This approach is preferred.
|
||||
- Add it to the spec itself.
|
||||
- Use `rubocop_spec_helper` for RuboCop related specs.
|
||||
|
||||
It takes around one second to load tests that are using `fast_spec_helper`
|
||||
instead of 30+ seconds in case of a regular `spec_helper`.
|
||||
Alternately, if it is a dependency which is required by many different `fast_spec_helper`
|
||||
specs in your domain, and you don't want to have to manually add the dependency many
|
||||
times, you can add it to be called directly from `fast_spec_helper` itself. To do
|
||||
this, you can create a `spec/support/fast_spec/YOUR_DOMAIN/fast_spec_helper_support.rb`
|
||||
file, and require it from `fast_spec_helper`. There are existing examples of this
|
||||
you can follow.
|
||||
|
||||
Use `rubocop_spec_helper` for RuboCop related specs.
|
||||
|
||||
WARNING:
|
||||
To verify that code and its specs are well-isolated from Rails, run the spec
|
||||
|
|
|
|||
|
|
@ -124,6 +124,43 @@ We also have a [reuseable base dropdown widget wrapper](https://gitlab.com/gitla
|
|||
1. Create the new widget in the [folder](https://gitlab.com/gitlab-org/gitlab/-/tree/master/app/assets/javascripts/work_items/components)
|
||||
1. If it is an editable widget in the sidebar , you should include it in [work_item_attributes_wrapper](https://gitlab.com/gitlab-org/gitlab/-/tree/master/app/assets/javascripts/work_items/components/work_item_attributes_wrapper.vue)
|
||||
|
||||
### Steps
|
||||
|
||||
Refer to [merge request #159720](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159720) for an example of the process of adding a new work item widget.
|
||||
|
||||
1. Define `I18N_WORK_ITEM_ERROR_FETCHING_<widget_name>` in `app/assets/javascripts/work_items/constants.js`.
|
||||
1. Create the component `app/assets/javascripts/work_items/components/work_item_<widget_name>.vue` or `ee/app/assets/javascripts/work_items/components/work_item_<widget_name>.vue`.
|
||||
- The component should not receive any props which are available from `workItemByIidQuery`- see [issue #461761](https://gitlab.com/gitlab-org/gitlab/-/issues/461761).
|
||||
1. Add the component to the view/edit work item screen `app/assets/javascripts/work_items/components/work_item_attributes_wrapper.vue`.
|
||||
1. If the widget is avaiable when creating new work items:
|
||||
1. Add the component to the create work item screen `app/assets/javascripts/work_items/components/create_work_item.vue`.
|
||||
1. Define a local input type `app/assets/javascripts/work_items/graphql/typedefs.graphql`.
|
||||
1. Stub the new work item state GraphQL data for the widget in `app/assets/javascripts/work_items/graphql/cache_utils.js`.
|
||||
1. Define how GraphQL updates the GraphQL data in `app/assets/javascripts/work_items/graphql/resolvers.js`.
|
||||
- A special `CLEAR_VALUE` constant is required for single value widgets, because we cannot differentiate when a value is `null` because we cleared it, or `null` because we did not
|
||||
set it.
|
||||
For example `ee/app/assets/javascripts/work_items/components/work_item_health_status.vue`.
|
||||
This is not required for most widgets which support multiple values, where we can differentiate between `[]` and `null`.
|
||||
- Read more about how [Apollo cache is being used to store values in create view](#apollo-cache-being-used-to-store-values-in-create-view).
|
||||
1. Add the GraphQL query for the widget:
|
||||
- For CE widgets, to `app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql` and `ee/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql`.
|
||||
- For EE widgets, to `ee/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql`.
|
||||
1. Update translations: `tooling/bin/gettext_extractor locale/gitlab.pot`.
|
||||
|
||||
At this point you should be able to use the widget in the frontend.
|
||||
|
||||
Now you can update tests for existing files and write tests for the new files:
|
||||
|
||||
1. `spec/frontend/work_items/components/create_work_item_spec.js` or `ee/spec/frontend/work_items/components/create_work_item_spec.js`.
|
||||
1. `spec/frontend/work_items/components/work_item_attributes_wrapper_spec.js` or `ee/spec/frontend/work_items/components/work_item_attributes_wrapper_spec.js`.
|
||||
1. `spec/frontend/work_items/components/work_item_<widget_name>_spec.js` or `ee/spec/frontend/work_items/components/work_item_<widget_name>_spec.js`.
|
||||
1. `spec/frontend/work_items/graphql/resolvers_spec.js` or `ee/spec/frontend/work_items/graphql/resolvers_spec.js`.
|
||||
1. `spec/features/projects/work_items/work_item_spec.rb` or `ee/spec/features/projects/work_items/work_item_spec.rb`.
|
||||
|
||||
NOTE:
|
||||
You may find some feature specs failing because of excissive SQL queries.
|
||||
To resolve this, update the mocked `Gitlab::QueryLimiting::Transaction.threshold` in `spec/support/shared_examples/features/work_items/rolledup_dates_shared_examples.rb`.
|
||||
|
||||
## Steps to implement a new work item widget on frontend in the create view
|
||||
|
||||
1. Make sure that you know the scope and have the designs ready for the new widget
|
||||
|
|
|
|||
|
|
@ -65,6 +65,14 @@ To enable Arkose Protect:
|
|||
ApplicationSetting.current.update(arkose_labs_private_api_key: '<your_private_api_key>')
|
||||
```
|
||||
|
||||
To disable Arkose Protect:
|
||||
|
||||
To disable the ArkoseLabs integration, run the following command in the Rails console.
|
||||
|
||||
```ruby
|
||||
Feature.disable(:arkose_labs)
|
||||
```
|
||||
|
||||
## Triage and debug ArkoseLabs issues
|
||||
|
||||
You can triage and debug issues raised by ArkoseLabs with:
|
||||
|
|
|
|||
|
|
@ -9,19 +9,30 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Status:** Beta
|
||||
|
||||
> - Introduced in GitLab 17.1 as an [experiment](../../../policy/experiment-beta-support.md) for Python.
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/461859) to beta in GitLab 17.2.
|
||||
|
||||
NOTE:
|
||||
This analyzer is in [beta](../../../policy/experiment-beta-support.md)
|
||||
and is subject to the [GitLab Testing Agreement](https://handbook.gitlab.com/handbook/legal/testing-agreement/).
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/474094) to GA in GitLab 17.3.
|
||||
|
||||
GitLab Advanced SAST is a Static Application Security Testing (SAST) analyzer
|
||||
designed to discover vulnerabilities by performing cross-function and cross-file taint analysis.
|
||||
|
||||
During the Beta phase, we advise running it side-by-side with your existing SAST analyzer, if any.
|
||||
GitLab Advanced SAST is an opt-in feature.
|
||||
When it is enabled, the GitLab Advanced SAST analyzer scans all the files of the supported languages,
|
||||
using the GitLab Advanced SAST predefined ruleset.
|
||||
The Semgrep analyzer will not scan these files.
|
||||
|
||||
All vulnerabilities identified by the GitLab Advanced SAST analyzer will be reported,
|
||||
including vulnerabilities previously reported by the Semgrep analyzer.
|
||||
An automated transition process is proposed for the future,
|
||||
in which the Vulnerability Management system will automatically de-duplicate findings
|
||||
that were identified by both the GitLab Advanced SAST analyzer and the Semgrep analyzer.
|
||||
It's proposed that the capability will be based on the advanced tracking algorithm
|
||||
and will keep the original record of the vulnerability
|
||||
(if it was first identified by Semgrep, then the Semgrep finding).
|
||||
|
||||
NOTE:
|
||||
In case a duplicated vulnerability was already introduced (in the interim time until the deduplication is available),the deduplication capability will not deduplicate it. The capability will be relevant only for validating new vulnerabilities that are not already duplicated.
|
||||
|
||||
By following the paths user inputs take, the analyzer identifies potential points
|
||||
where untrusted data can influence the execution of your application in unsafe ways,
|
||||
|
|
@ -43,6 +54,8 @@ GitLab Advanced SAST supports the following languages with cross-function and cr
|
|||
- Python
|
||||
- Go
|
||||
- Java
|
||||
- JavaScript
|
||||
- C#
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
@ -64,43 +77,19 @@ To enable the Advanced SAST analyzer:
|
|||
1. Select **Build > Pipeline editor**.
|
||||
1. If no `.gitlab-ci.yml` file exists, select **Configure pipeline**, then delete the example
|
||||
content.
|
||||
1. If there is already an include of `Jobs/SAST.latest.gitlab-ci.yml`,
|
||||
GitLab Advanced SAST is already configured.
|
||||
There is no additional step needed.
|
||||
1. If there is already an `include:` line, add `- template: Jobs/SAST.gitlab-ci.yml`
|
||||
below that line then paste only the `gitlab-advanced-sast:` block to the bottom of the file,
|
||||
otherwise paste the whole block to the bottom of the file.
|
||||
1. Include the latest SAST template `Jobs/SAST.latest.gitlab-ci.yml` (if not already done).
|
||||
**Note:** The `latest` templates can receive breaking changes in any release.
|
||||
1. Set the CI/CD variable `GITLAB_ADVANCED_SAST_ENABLED` to `true`.
|
||||
|
||||
```yaml
|
||||
include:
|
||||
- template: Jobs/SAST.gitlab-ci.yml
|
||||
Here is a minimal YAML file for enabling GitLab Advanced SAST:
|
||||
|
||||
gitlab-advanced-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SEARCH_MAX_DEPTH: 20
|
||||
SAST_ANALYZER_IMAGE_TAG: 0
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gitlab-advanced-sast:$SAST_ANALYZER_IMAGE_TAG$SAST_IMAGE_SUFFIX"
|
||||
rules:
|
||||
- if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'
|
||||
when: never
|
||||
- if: $SAST_EXCLUDED_ANALYZERS =~ /gitlab-advanced-sast/
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
|
||||
exists:
|
||||
- '**/*.py'
|
||||
- '**/*.go'
|
||||
- '**/*.java'
|
||||
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH # If there's no open merge request, add it to a *branch* pipeline instead.
|
||||
exists:
|
||||
- '**/*.py'
|
||||
- '**/*.go'
|
||||
- '**/*.java'
|
||||
```
|
||||
```yaml
|
||||
include:
|
||||
- template: Jobs/SAST.latest.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
GITLAB_ADVANCED_SAST_ENABLED: 'true'
|
||||
```
|
||||
|
||||
1. Select the **Validate** tab, then select **Validate pipeline**.
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ variables:
|
|||
SAST_IMAGE_SUFFIX: ""
|
||||
|
||||
SAST_EXCLUDED_ANALYZERS: ""
|
||||
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
|
||||
DEFAULT_SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
|
||||
SAST_EXCLUDED_PATHS: "$DEFAULT_SAST_EXCLUDED_PATHS"
|
||||
SCAN_KUBERNETES_MANIFESTS: "false"
|
||||
|
||||
sast:
|
||||
|
|
@ -50,13 +51,15 @@ gitlab-advanced-sast:
|
|||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SEARCH_MAX_DEPTH: 20
|
||||
SAST_ANALYZER_IMAGE_TAG: 0
|
||||
SAST_ANALYZER_IMAGE_TAG: 1
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gitlab-advanced-sast:$SAST_ANALYZER_IMAGE_TAG$SAST_IMAGE_SUFFIX"
|
||||
rules:
|
||||
- if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'
|
||||
when: never
|
||||
- if: $SAST_EXCLUDED_ANALYZERS =~ /gitlab-advanced-sast/
|
||||
when: never
|
||||
- if: $GITLAB_ADVANCED_SAST_ENABLED != 'true' && $GITLAB_ADVANCED_SAST_ENABLED != '1'
|
||||
when: never
|
||||
# Add the job to merge request pipelines if there's an open merge request.
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bsast_advanced\b/
|
||||
|
|
@ -64,6 +67,13 @@ gitlab-advanced-sast:
|
|||
- '**/*.py'
|
||||
- '**/*.go'
|
||||
- '**/*.java'
|
||||
- '**/*.js'
|
||||
- '**/*.jsx'
|
||||
- '**/*.ts'
|
||||
- '**/*.tsx'
|
||||
- '**/*.cjs'
|
||||
- '**/*.mjs'
|
||||
- '**/*.cs'
|
||||
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
|
||||
when: never
|
||||
# If there's no open merge request, add it to a *branch* pipeline instead.
|
||||
|
|
@ -73,6 +83,13 @@ gitlab-advanced-sast:
|
|||
- '**/*.py'
|
||||
- '**/*.go'
|
||||
- '**/*.java'
|
||||
- '**/*.js'
|
||||
- '**/*.jsx'
|
||||
- '**/*.ts'
|
||||
- '**/*.tsx'
|
||||
- '**/*.cjs'
|
||||
- '**/*.mjs'
|
||||
- '**/*.cs'
|
||||
|
||||
bandit-sast:
|
||||
extends: .sast-analyzer
|
||||
|
|
@ -183,13 +200,45 @@ semgrep-sast:
|
|||
when: never
|
||||
- if: $SAST_EXCLUDED_ANALYZERS =~ /semgrep/
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
|
||||
# Add the job to merge request pipelines if there's an open merge request.
|
||||
## In case gitlab-advanced-sast also runs, exclude files already scanned by gitlab-advanced-sast
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bsast_advanced\b/ &&
|
||||
$SAST_EXCLUDED_ANALYZERS !~ /gitlab-advanced-sast/ &&
|
||||
($GITLAB_ADVANCED_SAST_ENABLED == 'true' || $GITLAB_ADVANCED_SAST_ENABLED == '1')
|
||||
variables:
|
||||
SAST_EXCLUDED_PATHS: "$DEFAULT_SAST_EXCLUDED_PATHS, **/*.py, **/*.go, **/*.java, **/*.js, **/*.jsx, **/*.ts, **/*.tsx, **/*.cjs, **/*.mjs, **/*.cs"
|
||||
exists:
|
||||
- '**/*.c'
|
||||
- '**/*.cc'
|
||||
- '**/*.cpp'
|
||||
- '**/*.c++'
|
||||
- '**/*.cp'
|
||||
- '**/*.cxx'
|
||||
- '**/*.h'
|
||||
- '**/*.hpp'
|
||||
- '**/*.scala'
|
||||
- '**/*.sc'
|
||||
- '**/*.php'
|
||||
- '**/*.swift'
|
||||
- '**/*.m'
|
||||
- '**/*.rb'
|
||||
- '**/*.kt'
|
||||
## In case gitlab-advanced-sast already covers all the files that semgrep-sast would have scanned
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bsast_advanced\b/ &&
|
||||
$SAST_EXCLUDED_ANALYZERS !~ /gitlab-advanced-sast/ &&
|
||||
($GITLAB_ADVANCED_SAST_ENABLED == 'true' || $GITLAB_ADVANCED_SAST_ENABLED == '1')
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
exists:
|
||||
- '**/*.py'
|
||||
- '**/*.js'
|
||||
- '**/*.jsx'
|
||||
- '**/*.ts'
|
||||
- '**/*.tsx'
|
||||
- '**/*.cjs'
|
||||
- '**/*.mjs'
|
||||
- '**/*.c'
|
||||
- '**/*.cc'
|
||||
- '**/*.cpp'
|
||||
|
|
@ -208,17 +257,47 @@ semgrep-sast:
|
|||
- '**/*.m'
|
||||
- '**/*.rb'
|
||||
- '**/*.kt'
|
||||
- '**/*.cjs'
|
||||
- '**/*.mjs'
|
||||
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH # If there's no open merge request, add it to a *branch* pipeline instead.
|
||||
# If there's no open merge request, add it to a *branch* pipeline instead.
|
||||
## In case gitlab-advanced-sast also runs, exclude files already scanned by gitlab-advanced-sast
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bsast_advanced\b/ &&
|
||||
$SAST_EXCLUDED_ANALYZERS !~ /gitlab-advanced-sast/ &&
|
||||
($GITLAB_ADVANCED_SAST_ENABLED == 'true' || $GITLAB_ADVANCED_SAST_ENABLED == '1')
|
||||
variables:
|
||||
SAST_EXCLUDED_PATHS: "$DEFAULT_SAST_EXCLUDED_PATHS, **/*.py, **/*.go, **/*.java, **/*.js, **/*.jsx, **/*.ts, **/*.tsx, **/*.cjs, **/*.mjs, **/*.cs"
|
||||
exists:
|
||||
- '**/*.c'
|
||||
- '**/*.cc'
|
||||
- '**/*.cpp'
|
||||
- '**/*.c++'
|
||||
- '**/*.cp'
|
||||
- '**/*.cxx'
|
||||
- '**/*.h'
|
||||
- '**/*.hpp'
|
||||
- '**/*.scala'
|
||||
- '**/*.sc'
|
||||
- '**/*.php'
|
||||
- '**/*.swift'
|
||||
- '**/*.m'
|
||||
- '**/*.rb'
|
||||
- '**/*.kt'
|
||||
## In case gitlab-advanced-sast already covers all the files that semgrep-sast would have scanned
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bsast_advanced\b/ &&
|
||||
$SAST_EXCLUDED_ANALYZERS !~ /gitlab-advanced-sast/ &&
|
||||
($GITLAB_ADVANCED_SAST_ENABLED == 'true' || $GITLAB_ADVANCED_SAST_ENABLED == '1')
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
exists:
|
||||
- '**/*.py'
|
||||
- '**/*.js'
|
||||
- '**/*.jsx'
|
||||
- '**/*.ts'
|
||||
- '**/*.tsx'
|
||||
- '**/*.cjs'
|
||||
- '**/*.mjs'
|
||||
- '**/*.c'
|
||||
- '**/*.cc'
|
||||
- '**/*.cpp'
|
||||
|
|
@ -237,8 +316,6 @@ semgrep-sast:
|
|||
- '**/*.m'
|
||||
- '**/*.rb'
|
||||
- '**/*.kt'
|
||||
- '**/*.cjs'
|
||||
- '**/*.mjs'
|
||||
|
||||
sobelow-sast:
|
||||
extends: .sast-analyzer
|
||||
|
|
|
|||
|
|
@ -48,47 +48,56 @@ module Gitlab
|
|||
[404, { 'Content-Type' => 'text/plain' }, [not_found_message]]
|
||||
end
|
||||
|
||||
# handle_go_get_request returns a go get HTML document response if the project exists and the user has read access
|
||||
# otherwise it returns a 404 response with a message for the go toolchain to display.
|
||||
# handle_go_get_request responds to `go get` requests by either returning a successful 200
|
||||
# response with meta tags as described in https://go.dev/ref/mod, or a 404 response with a
|
||||
# message that the go toolchain will display.
|
||||
#
|
||||
# The go toolchain authenticates using basic auth. When credentials are not present, a
|
||||
# successful response is always returned as if a project exists (using a two-segment path
|
||||
# like `namespace/project`) in order to prevent leaking information about the existence of
|
||||
# private projects, and to maintain backwards compatibility for users who have not set up
|
||||
# authentication for their go toolchain.
|
||||
def handle_go_get_request(request)
|
||||
path_info = request.env["PATH_INFO"].delete_prefix('/')
|
||||
project = project_for_path(path_info)
|
||||
|
||||
# return the same way when a repo is not found or the user has no access
|
||||
# so that we don't reveal the existence of a project the user doesn't have access to.
|
||||
return not_found_response unless project&.repository_exists?
|
||||
return not_found_response unless can_read_project?(request, project)
|
||||
if project && can_read_project?(request, project)
|
||||
return not_found_response unless project.repository_exists?
|
||||
|
||||
html = create_go_get_html(project)
|
||||
response = Rack::Response.new(html, 200, { 'Content-Type' => 'text/html' })
|
||||
response.finish
|
||||
create_go_get_html_response(project.full_path)
|
||||
elsif request.authorization.present?
|
||||
not_found_response
|
||||
else
|
||||
path_segments = path_info.split('/')
|
||||
return not_found_response unless path_segments.length >= 2
|
||||
|
||||
two_segment_path = path_segments.first(2).join('/')
|
||||
|
||||
create_go_get_html_response(two_segment_path)
|
||||
end
|
||||
end
|
||||
|
||||
def go_get_request?(request)
|
||||
request["go-get"].to_i == 1 && request.env["PATH_INFO"].present?
|
||||
end
|
||||
|
||||
# create_go_get_html creates a HTML document for go get with the expected meta tags.
|
||||
def create_go_get_html(project)
|
||||
# See https://go.dev/ref/mod for documentation on the `go-import` meta tag.
|
||||
root_path = Gitlab::Utils.append_path(Gitlab.config.gitlab.host, project.full_path)
|
||||
repo_url = Gitlab::CurrentSettings.enabled_git_access_protocol == 'ssh' ? ssh_url(project.full_path) : project.http_url_to_repo
|
||||
def get_repo_url(project_full_path)
|
||||
return ssh_url(project_full_path) if Gitlab::CurrentSettings.enabled_git_access_protocol == 'ssh'
|
||||
|
||||
Gitlab::RepositoryUrlBuilder.build(project_full_path, protocol: :http)
|
||||
end
|
||||
|
||||
# create_go_get_html_response creates a HTML document for go get with the expected meta tags.
|
||||
def create_go_get_html_response(project_full_path)
|
||||
root_path = Gitlab::Utils.append_path(Gitlab.config.gitlab.host, project_full_path)
|
||||
repo_url = get_repo_url(project_full_path)
|
||||
go_import_meta_tag = tag.meta(name: 'go-import', content: "#{root_path} git #{repo_url}")
|
||||
|
||||
# See https://github.com/golang/gddo/wiki/Source-Code-Links for documentation on the `go-source` meta tag.
|
||||
if project.default_branch
|
||||
source_home = Gitlab::Utils.append_path(Gitlab.config.gitlab.url, project.full_path)
|
||||
source_directory = "#{source_home}/-/tree/#{project.default_branch}{/dir}"
|
||||
source_file = "#{source_home}/-/blob/#{project.default_branch}{/dir}/{file}#L{line}"
|
||||
go_source_meta_tag = tag.meta(name: 'go-source', content: "#{root_path} #{source_home} #{source_directory} #{source_file}")
|
||||
head_tag = content_tag :head, go_import_meta_tag + go_source_meta_tag
|
||||
else
|
||||
head_tag = content_tag :head, go_import_meta_tag
|
||||
end
|
||||
|
||||
head_tag = content_tag :head, go_import_meta_tag
|
||||
body_tag = content_tag :body, "go get #{root_path}"
|
||||
html = content_tag :html, head_tag + body_tag
|
||||
|
||||
content_tag :html, head_tag + body_tag
|
||||
response = Rack::Response.new(html, 200, { 'Content-Type' => 'text/html' })
|
||||
response.finish
|
||||
end
|
||||
|
||||
# project_for_path searches for a project based on the path_info
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'json_schemer'
|
||||
|
||||
module WebIde
|
||||
module Settings
|
||||
class ExtensionsGalleryValidator
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
||||
|
||||
msgid " %{link_start}Learn More%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid " %{start} to %{end}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -8197,9 +8194,6 @@ msgstr ""
|
|||
msgid "Because you enabled auto-banning, we have also automatically banned this user from %{scope}. If this is a mistake, you can unban them: %{url}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Before enabling this integration, create a webhook for the space in Google Chat where you want to receive notifications from this project. %{docs_link}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Before inserting code, be sure to read the comment that separated each code group."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -14208,9 +14202,6 @@ msgstr ""
|
|||
msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar. Enabling this integration replaces the \"Wiki\" sidebar link with a link to the Confluence Workspace. The GitLab wiki is still available at the original URL."
|
||||
msgstr ""
|
||||
|
||||
msgid "ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To re-enable the link to the GitLab wiki, disable this integration."
|
||||
msgstr ""
|
||||
|
||||
msgid "Congratulations, your free trial is activated."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -17203,7 +17194,7 @@ msgstr ""
|
|||
msgid "Database update failed"
|
||||
msgstr ""
|
||||
|
||||
msgid "DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog."
|
||||
msgid "DatadogIntegration|%{link_start}API key%{link_end} used for authentication with Datadog."
|
||||
msgstr ""
|
||||
|
||||
msgid "DatadogIntegration|(Advanced) The full URL for your Datadog site."
|
||||
|
|
@ -17221,10 +17212,7 @@ msgstr ""
|
|||
msgid "DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}"
|
||||
msgstr ""
|
||||
|
||||
msgid "DatadogIntegration|How do I set up this integration?"
|
||||
msgstr ""
|
||||
|
||||
msgid "DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues. %{docs_link}"
|
||||
msgid "DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues."
|
||||
msgstr ""
|
||||
|
||||
msgid "DatadogIntegration|Service"
|
||||
|
|
@ -22892,6 +22880,9 @@ msgstr ""
|
|||
msgid "For more information, go to the "
|
||||
msgstr ""
|
||||
|
||||
msgid "For more information, see the %{link_start}documentation%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "For more information, see the developer console. Try to reload the page or sign out and in again. If the issue persists, %{reportIssueStart}report a problem%{reportIssueEnd}."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -26579,6 +26570,9 @@ msgstr ""
|
|||
msgid "How do I set up a Google Chat webhook?"
|
||||
msgstr ""
|
||||
|
||||
msgid "How do I set up this integration?"
|
||||
msgstr ""
|
||||
|
||||
msgid "How do I set up this service?"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46568,9 +46562,6 @@ msgstr ""
|
|||
msgid "Scan pushed document contents for policy breaks. %{docs_link}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanExecutionPolicy|%{boldStart}Run%{boldEnd} %{typeSelector} %{actionType}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanExecutionPolicy|%{boldStart}Run%{boldEnd} %{typeSelector} from the project %{projectSelector} with ref %{refSelector}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46640,9 +46631,6 @@ msgstr ""
|
|||
msgid "ScanExecutionPolicy|File reference (Optional) %{refSelector}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanExecutionPolicy|If there are any conflicting variables with the local pipeline configuration (Ex, gitlab-ci.yml) then variables defined here will take precedence. %{linkStart}Learn more%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanExecutionPolicy|Inject"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46898,13 +46886,19 @@ msgstr ""
|
|||
msgid "ScanResultPolicy|Pre-existing"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|Prevent %{linkStart}group branch%{linkEnd} modification %{exceptSelection}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|Prevent %{linkStart}group branch%{linkEnd} modification %{exceptSelection} matching the wildcard pattern: %{projectSelection}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|Prevent approval by commit author"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|Prevent approval by merge request's author"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|Prevent branch modification"
|
||||
msgid "ScanResultPolicy|Prevent project branch modification"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|Prevent pushing and force pushing"
|
||||
|
|
@ -46970,7 +46964,10 @@ msgstr ""
|
|||
msgid "ScanResultPolicy|When enabled, merge request authors cannot approve their own MRs."
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|When enabled, prevents a user from removing a branch from the protected branches list, deleting a protected branch, or changing the default branch if that branch is included in the security policy."
|
||||
msgid "ScanResultPolicy|When enabled, prevents a user from removing a branch from the group protected branches list, deleting a protected branch, or changing the default branch if that branch is included in the security policy."
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|When enabled, prevents a user from removing a branch from the project protected branches list, deleting a protected branch, or changing the default branch if that branch is included in the security policy."
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanResultPolicy|When enabled, prevents pushing and force pushing to a protected branch if that branch is included in the security policy."
|
||||
|
|
@ -47973,9 +47970,6 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Enforce %{linkStart}security policies%{linkEnd} for this project."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Enforce custom CI with pipeline execution action for scan execution policies. %{linkStart}How do I implement this feature?%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Enforce policy on all groups, subgroups, and projects linked to the security policy project. %{linkStart}How does scoping work?%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -47985,6 +47979,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Every time a pipeline runs for %{branches}%{branchExceptionsString}"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Ex: development/*"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Exception branches"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -48051,9 +48048,6 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Inherited from %{namespace}"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Introducing Pipeline Execution Policy Action experimental feature"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Invalid Compliance Framework ID(s)"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -48305,9 +48299,6 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Severity is %{severity}."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Share feedback"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Show all included projects"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -48560,6 +48551,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|default"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|except branches"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|except projects"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -49381,9 +49375,6 @@ msgstr ""
|
|||
msgid "Send notifications about project events to Mattermost channels."
|
||||
msgstr ""
|
||||
|
||||
msgid "Send notifications about project events to a Discord channel. %{docs_link}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Send notifications for broken pipelines."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@
|
|||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/fonts": "^1.3.0",
|
||||
"@gitlab/svgs": "3.109.0",
|
||||
"@gitlab/ui": "87.6.1",
|
||||
"@gitlab/ui": "87.7.0",
|
||||
"@gitlab/web-ide": "^0.0.1-dev-20240613133550",
|
||||
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
|
||||
"@rails/actioncable": "7.0.8-4",
|
||||
|
|
|
|||
|
|
@ -8,74 +8,89 @@ BGreen='\033[1;32m'
|
|||
BBlue='\033[1;34m'
|
||||
Color_Off='\033[0m'
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
trap onexit_err ERR
|
||||
|
||||
# Exit handling
|
||||
function onexit_err() {
|
||||
local exit_status=${1:-$?}
|
||||
printf "\n❌❌❌ ${BRed}Remote Development smoke test failed!${Color_Off} ❌❌❌\n"
|
||||
if [ "${REVEAL_RUBOCOP_TODO}" -ne 0 ]; then
|
||||
printf "\n(If the failure was due to rubocop, set REVEAL_RUBOCOP_TODO=0 to ignore TODOs)\n"
|
||||
printf "\n${BRed}- If the failure was due to rubocop, try setting REVEAL_RUBOCOP_TODO=0 to ignore TODOs${Color_Off}\n"
|
||||
fi
|
||||
|
||||
printf "\n${BRed}- If the failure was in a feature spec, those sometimes are flaky, try running it focused${Color_Off}\n"
|
||||
|
||||
exit "${exit_status}"
|
||||
}
|
||||
trap onexit_err ERR
|
||||
set -o errexit
|
||||
|
||||
function print_start_message {
|
||||
trap onexit_err ERR
|
||||
|
||||
printf "${BCyan}\nStarting Remote Development smoke test...${Color_Off}\n\n"
|
||||
}
|
||||
|
||||
function run_rubocop {
|
||||
trap onexit_err ERR
|
||||
|
||||
printf "${BBlue}Running RuboCop${Color_Off}\n\n"
|
||||
|
||||
files_for_rubocop=()
|
||||
while IFS= read -r -d '' file; do
|
||||
|
||||
while IFS='' read -r file; do
|
||||
files_for_rubocop+=("$file")
|
||||
done < <(find app lib spec ee/app ee/lib ee/spec \( -path '**/remote_development/*.rb' -o -path '**/gitlab/fp/*.rb' \) -print0)
|
||||
files_for_rubocop+=(
|
||||
"spec/support/matchers/invoke_rop_steps.rb"
|
||||
"spec/support/railway_oriented_programming.rb"
|
||||
"spec/support_specs/matchers/result_matchers_spec.rb"
|
||||
)
|
||||
done < <(git ls-files -- '**/remote_development/*.rb' '**/gitlab/fp/*.rb' '*_rop_*.rb' '*railway_oriented_programming*.rb' '*_result_matchers*.rb')
|
||||
|
||||
REVEAL_RUBOCOP_TODO=${REVEAL_RUBOCOP_TODO:-1} bundle exec rubocop --parallel --force-exclusion --no-server "${files_for_rubocop[@]}"
|
||||
}
|
||||
|
||||
function run_fp {
|
||||
trap onexit_err ERR
|
||||
|
||||
printf "\n\n${BBlue}Running backend RSpec FP specs${Color_Off}\n\n"
|
||||
|
||||
files_for_fp=()
|
||||
|
||||
while IFS= read -r file; do
|
||||
while IFS='' read -r file; do
|
||||
files_for_fp+=("$file")
|
||||
done < <(find spec/lib/gitlab/fp -path '**/*_spec.rb')
|
||||
done < <(git ls-files -- '**/gitlab/fp/*_spec.rb')
|
||||
|
||||
|
||||
bin/rspec "${files_for_fp[@]}"
|
||||
}
|
||||
|
||||
function run_rspec_fast {
|
||||
printf "\n\n${BBlue}Running backend RSpec fast specs${Color_Off}\n\n"
|
||||
trap onexit_err ERR
|
||||
|
||||
# NOTE: We do not use `--tag rd_fast` here, because `rd_fast_spec_helper` has a check to ensure that all the
|
||||
# files which require it are tagged with `rd_fast`.
|
||||
printf "\n\n${BBlue}Running backend RSpec fast specs${Color_Off}\n\n"
|
||||
|
||||
files_for_fast=()
|
||||
|
||||
while IFS= read -r file; do
|
||||
while IFS='' read -r file; do
|
||||
files_for_fast+=("$file")
|
||||
done < <(find spec ee/spec -path '**/remote_development/*_spec.rb' -exec grep -lE 'require_relative.*rd_fast_spec_helper' {} +)
|
||||
done < <(git grep -l -E '^require .fast_spec_helper' -- '**/remote_development/*_spec.rb')
|
||||
|
||||
bin/rspec "${files_for_fast[@]}"
|
||||
}
|
||||
|
||||
function run_jest {
|
||||
trap onexit_err ERR
|
||||
|
||||
printf "\n\n${BBlue}Running Remote Development frontend Jest specs${Color_Off}\n\n"
|
||||
yarn jest ee/spec/frontend/workspaces
|
||||
}
|
||||
|
||||
function run_rspec_rails {
|
||||
function run_rspec_rails_non_fast {
|
||||
trap onexit_err ERR
|
||||
|
||||
printf "\n\n${BBlue}Running backend RSpec non-fast specs${Color_Off}\n\n"
|
||||
|
||||
files_for_rails=()
|
||||
while IFS= read -r file; do
|
||||
|
||||
while IFS='' read -r file; do
|
||||
files_for_rails+=("$file")
|
||||
done < <(find spec ee/spec -path '**/remote_development/*_spec.rb' | grep -v 'qa/qa' | grep -v '/features/')
|
||||
done < <(git grep -L -E '^require .fast_spec_helper' -- '**/remote_development/*_spec.rb' | grep -v 'qa/qa' | grep -v '/features/')
|
||||
|
||||
files_for_rails+=(
|
||||
"ee/spec/graphql/types/query_type_spec.rb"
|
||||
|
|
@ -85,15 +100,17 @@ function run_rspec_rails {
|
|||
"spec/support_specs/matchers/result_matchers_spec.rb"
|
||||
)
|
||||
|
||||
bin/rspec -r spec_helper --tag ~rd_fast "${files_for_rails[@]}"
|
||||
bin/rspec "${files_for_rails[@]}"
|
||||
}
|
||||
|
||||
function run_rspec_feature {
|
||||
printf "\n\n${BBlue}Running backend RSpec feature specs${Color_Off}\n\n"
|
||||
trap onexit_err ERR
|
||||
|
||||
printf "\n\n${BBlue}Running backend RSpec feature specs (NOTE: These sometimes are flaky! If one fails, try running it focused)...${Color_Off}\n\n"
|
||||
files_for_feature=()
|
||||
while IFS= read -r file; do
|
||||
while IFS='' read -r file; do
|
||||
files_for_feature+=("$file")
|
||||
done < <(find ee/spec -path '**/remote_development/*_spec.rb' | grep -v 'qa/qa' | grep '/features/')
|
||||
done < <(git ls-files -- '**/remote_development/*_spec.rb' | grep -v 'qa/qa' | grep '/features/')
|
||||
|
||||
bin/rspec -r spec_helper "${files_for_feature[@]}"
|
||||
}
|
||||
|
|
@ -103,6 +120,8 @@ function print_success_message {
|
|||
}
|
||||
|
||||
function main {
|
||||
trap onexit_err ERR
|
||||
|
||||
# cd to gitlab root directory
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")"/../..
|
||||
|
||||
|
|
@ -115,7 +134,7 @@ function main {
|
|||
[ -z "${SKIP_FP}" ] && run_fp
|
||||
[ -z "${SKIP_FAST}" ] && run_rspec_fast
|
||||
[ -z "${SKIP_JEST}" ] && run_jest
|
||||
[ -z "${SKIP_RAILS}" ] && run_rspec_rails
|
||||
[ -z "${SKIP_RAILS}" ] && run_rspec_rails_non_fast
|
||||
[ -z "${SKIP_FEATURE}" ] && run_rspec_feature
|
||||
|
||||
print_success_message
|
||||
|
|
|
|||
|
|
@ -7,29 +7,90 @@ if $LOADED_FEATURES.include?(File.expand_path('spec_helper.rb', __dir__))
|
|||
end
|
||||
|
||||
require_relative '../config/bundler_setup'
|
||||
require 'benchmark'
|
||||
|
||||
ENV['IN_MEMORY_APPLICATION_SETTINGS'] = 'true'
|
||||
module FastSpecHelper
|
||||
def self.slower_app_requires
|
||||
require 'active_support/all'
|
||||
require 'pry'
|
||||
end
|
||||
|
||||
require_relative 'deprecation_warnings'
|
||||
def self.app_requires
|
||||
require_relative 'deprecation_warnings'
|
||||
require 'gitlab/utils/all'
|
||||
require_relative 'rails_autoload'
|
||||
ENV['IN_MEMORY_APPLICATION_SETTINGS'] = 'true'
|
||||
require_relative '../config/settings'
|
||||
require_relative '../lib/gitlab'
|
||||
end
|
||||
|
||||
# Enable zero monkey patching mode before loading any other RSpec code.
|
||||
RSpec.configure(&:disable_monkey_patching!)
|
||||
def self.slower_spec_requires
|
||||
require 'rspec-parameterized'
|
||||
require_relative 'support/rspec'
|
||||
end
|
||||
|
||||
require 'active_support/all'
|
||||
require 'pry'
|
||||
require 'gitlab/utils/all'
|
||||
require_relative 'rails_autoload'
|
||||
def self.spec_requires_and_configuration
|
||||
require 'gitlab/rspec/next_instance_of'
|
||||
require_relative 'support/matchers/result_matchers'
|
||||
require_relative 'support/railway_oriented_programming'
|
||||
require_relative 'simplecov_env'
|
||||
|
||||
require_relative '../config/settings'
|
||||
require_relative 'support/rspec'
|
||||
require_relative '../lib/gitlab'
|
||||
# NOTE: Consider making any common RSpec configuration tweaks in `spec/support/rspec.rb` instead of here,
|
||||
# because it is also used by `spec/spec_helper.rb`.
|
||||
RSpec.configure do |config|
|
||||
config.include NextInstanceOf
|
||||
config.disable_monkey_patching! # Enable zero monkey patching mode before loading any other RSpec code.
|
||||
config.mock_with :rspec do |mocks|
|
||||
mocks.verify_doubled_constant_names = false # Allow mocking of non-lib module/class names from Rails
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require_relative 'simplecov_env'
|
||||
SimpleCovEnv.start!
|
||||
def self.domain_specific_spec_helper_support
|
||||
# If you want to extensively use `fast_spec_helper` for your domain or
|
||||
# bounded context (https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/modular_monolith/bounded_contexts/),
|
||||
# but don't want to have to repeat the same require statement or configuration across multiple spec files, you can
|
||||
# add a custom fast_spec_helper for your domain and require it here.
|
||||
# Just make sure your additions don't do anything to noticably increase the runtime of `fast_spec_helper`!
|
||||
|
||||
ActiveSupport::XmlMini.backend = 'Nokogiri'
|
||||
# Remote Development domain
|
||||
require_relative('../ee/spec/support/fast_spec/remote_development/fast_spec_helper_support') if Gitlab.ee?
|
||||
|
||||
# Consider tweaking configuration in `spec/support/rspec.rb` which is also
|
||||
# used by `spec/spec_helper.rb`.
|
||||
# Web IDE domain
|
||||
require_relative 'support/fast_spec/web_ide/fast_spec_helper_support'
|
||||
end
|
||||
|
||||
def self.post_require_configuration
|
||||
SimpleCovEnv.start!
|
||||
ActiveSupport::XmlMini.backend = 'Nokogiri'
|
||||
end
|
||||
|
||||
def self.with_slow_execution_warning(max_allowed:)
|
||||
data = Benchmark.measure do
|
||||
yield
|
||||
end
|
||||
|
||||
total = data.total
|
||||
|
||||
return if total < max_allowed
|
||||
|
||||
warn "\n\nWarning: fast_spec_helper submodule took longer than max allowed execution time " \
|
||||
"of #{max_allowed}: #{total}\n"
|
||||
warn "Slow submodule invoked from: #{caller[0]}\n\n"
|
||||
end
|
||||
|
||||
def self.run
|
||||
# NOTE: These max_allowed times are generally 2-4 times higher than the actual average
|
||||
# execution times, to avoid false warnings on slower machines or CI runners.
|
||||
with_slow_execution_warning(max_allowed: 2.0) { slower_app_requires }
|
||||
with_slow_execution_warning(max_allowed: 0.2) { app_requires }
|
||||
with_slow_execution_warning(max_allowed: 1.0) { slower_spec_requires }
|
||||
with_slow_execution_warning(max_allowed: 0.2) { spec_requires_and_configuration }
|
||||
with_slow_execution_warning(max_allowed: 1.0) { domain_specific_spec_helper_support }
|
||||
with_slow_execution_warning(max_allowed: 0.2) { post_require_configuration }
|
||||
end
|
||||
end
|
||||
|
||||
FastSpecHelper.run
|
||||
|
||||
require_relative('../jh/spec/fast_spec_helper') if Gitlab.jh?
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { GlModal } from '@gitlab/ui';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import Vuex from 'vuex';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
|
||||
import createStore from '~/deploy_freeze/store';
|
||||
import { RECEIVE_FREEZE_PERIODS_SUCCESS } from '~/deploy_freeze/store/mutation_types';
|
||||
|
|
@ -21,18 +21,19 @@ describe('Deploy freeze table', () => {
|
|||
timezoneData: timezoneDataFixture,
|
||||
});
|
||||
jest.spyOn(store, 'dispatch').mockImplementation();
|
||||
wrapper = mount(DeployFreezeTable, {
|
||||
wrapper = mountExtended(DeployFreezeTable, {
|
||||
attachTo: document.body,
|
||||
store,
|
||||
});
|
||||
};
|
||||
|
||||
const findEmptyFreezePeriods = () => wrapper.find('[data-testid="empty-freeze-periods"]');
|
||||
const findAddDeployFreezeButton = () => wrapper.find('[data-testid="add-deploy-freeze"]');
|
||||
const findEditDeployFreezeButton = () => wrapper.find('[data-testid="edit-deploy-freeze"]');
|
||||
const findDeployFreezeTable = () => wrapper.find('[data-testid="deploy-freeze-table"]');
|
||||
const findDeleteDeployFreezeButton = () => wrapper.find('[data-testid="delete-deploy-freeze"]');
|
||||
const findEmptyFreezePeriods = () => wrapper.findByTestId('empty-freeze-periods');
|
||||
const findAddDeployFreezeButton = () => wrapper.findByTestId('add-deploy-freeze');
|
||||
const findEditDeployFreezeButton = () => wrapper.findByTestId('edit-deploy-freeze');
|
||||
const findDeployFreezeTable = () => wrapper.findByTestId('deploy-freeze-table');
|
||||
const findDeleteDeployFreezeButton = () => wrapper.findByTestId('delete-deploy-freeze');
|
||||
const findDeleteDeployFreezeModal = () => wrapper.findComponent(GlModal);
|
||||
const findCount = () => wrapper.findByTestId('crud-count');
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
|
|
@ -65,6 +66,12 @@ describe('Deploy freeze table', () => {
|
|||
expect(findEditDeployFreezeButton().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('displays correct count', () => {
|
||||
const tableRows = findDeployFreezeTable().findAll('tbody tr');
|
||||
expect(tableRows.length).toBe(freezePeriodsFixture.length);
|
||||
expect(findCount().text()).toBe('3');
|
||||
});
|
||||
|
||||
it('allows user to edit deploy freeze', async () => {
|
||||
findEditDeployFreezeButton().trigger('click');
|
||||
await nextTick();
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ RSpec.describe 'cross-database foreign keys' do
|
|||
'subscription_add_on_purchases.subscription_add_on_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/444666
|
||||
'sbom_component_versions.component_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/469535
|
||||
'sbom_occurrences.component_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/469535
|
||||
'sbom_occurrences.component_version_id', # https://gitlab.com/groups/gitlab-org/-/epics/14116#identified-cross-joins
|
||||
'sbom_occurrences.source_id', # https://gitlab.com/groups/gitlab-org/-/epics/14116#identified-cross-joins
|
||||
'sbom_occurrences.source_package_id', # https://gitlab.com/groups/gitlab-org/-/epics/14116#identified-cross-joins
|
||||
'vulnerability_export_parts.vulnerability_export_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/473014
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'fast_spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Fp::Message, :rd_fast, feature_category: :shared do
|
||||
RSpec.describe Gitlab::Fp::Message, feature_category: :shared do
|
||||
describe '#==' do
|
||||
it 'implements equality' do
|
||||
expect(described_class.new({ a: 1 })).to eq(described_class.new(a: 1))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'fast_spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Fp::MessageSupport, :rd_fast, feature_category: :shared do
|
||||
RSpec.describe Gitlab::Fp::MessageSupport, feature_category: :shared do
|
||||
let(:extending_class) do
|
||||
Class.new do
|
||||
extend Gitlab::Fp::MessageSupport
|
||||
|
|
|
|||
|
|
@ -38,27 +38,56 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
let(:path) { "#{project.full_path}/subpackage" }
|
||||
|
||||
it 'returns the full project path', :unlimited_max_formatted_output_length do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch)
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without subpackages' do
|
||||
let(:path) { project.full_path }
|
||||
|
||||
it 'returns the full project path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the project is private' do
|
||||
let(:path) { project.full_path }
|
||||
|
||||
before do
|
||||
project.update_attribute(:visibility_level, Project::PRIVATE)
|
||||
context 'when the project is public' do
|
||||
it 'returns the full project path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns 404' do
|
||||
expect_404_response(go)
|
||||
context 'when the project is private' do
|
||||
before do
|
||||
project.update_attribute(:visibility_level, Project::PRIVATE)
|
||||
end
|
||||
|
||||
context 'when authorization header is not present' do
|
||||
it 'returns the 2-segment path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authorization header is present but invalid' do
|
||||
before do
|
||||
env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials('invalid', 'invalid')
|
||||
end
|
||||
|
||||
it 'returns 404' do
|
||||
expect_404_response(go)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated' do
|
||||
let(:current_user) { project.creator }
|
||||
let(:personal_access_token) { create(:personal_access_token, user: current_user) }
|
||||
|
||||
before do
|
||||
env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(current_user.username, personal_access_token.token)
|
||||
end
|
||||
|
||||
context 'when the project accessed by a redirect' do
|
||||
let!(:redirect_route) { create(:redirect_route, source: project, path: 'redirect/project') }
|
||||
|
||||
it 'returns the full project path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when feature flag is disabled' do
|
||||
|
|
@ -66,20 +95,11 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
stub_feature_flags(not_found_response_for_go_get: false)
|
||||
end
|
||||
|
||||
it 'returns the full project path' do
|
||||
it 'returns the full project path', :unlimited_max_formatted_output_length do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the project accessed by a redirect' do
|
||||
let!(:redirect_route) { create(:redirect_route, source: project, path: 'redirect/project') }
|
||||
let(:path) { redirect_route.path }
|
||||
|
||||
it 'returns the full project path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a nested project path' do
|
||||
|
|
@ -89,7 +109,7 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
shared_examples 'a nested project' do
|
||||
context 'when the project is public' do
|
||||
it 'returns the full project path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch)
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -98,54 +118,52 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
project.update_attribute(:visibility_level, Project::PRIVATE)
|
||||
end
|
||||
|
||||
shared_examples 'unauthorized' do
|
||||
shared_examples 'when no authentication header' do
|
||||
it 'returns the 2-segment group path' do
|
||||
expect_response_with_path(go, enabled_protocol, group.full_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid authentication header exists' do
|
||||
before do
|
||||
env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials('invalid', 'invalid')
|
||||
end
|
||||
|
||||
it 'returns 404' do
|
||||
expect_404_response(go)
|
||||
end
|
||||
|
||||
context 'when feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(not_found_response_for_go_get: false)
|
||||
end
|
||||
|
||||
it 'returns the 2-segment group path' do
|
||||
expect_response_with_path(go, enabled_protocol, group.full_path, project.default_branch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not authenticated' do
|
||||
it_behaves_like 'unauthorized'
|
||||
end
|
||||
|
||||
context 'when authenticated' do
|
||||
shared_examples 'when authenticated' do
|
||||
let(:current_user) { project.creator }
|
||||
|
||||
before do
|
||||
project.team.add_maintainer(current_user)
|
||||
end
|
||||
|
||||
shared_examples 'authenticated' do
|
||||
context 'with access to the project' do
|
||||
it 'returns the full project path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path, project.default_branch)
|
||||
end
|
||||
context 'with access to the project' do
|
||||
it 'returns the full project path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without access to the project', :sidekiq_inline do
|
||||
before do
|
||||
project.team.find_member(current_user).destroy!
|
||||
end
|
||||
|
||||
context 'without access to the project', :sidekiq_inline do
|
||||
before do
|
||||
project.team.find_member(current_user).destroy!
|
||||
end
|
||||
it 'returns 404' do
|
||||
expect_404_response(go)
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'unauthorized'
|
||||
context 'with user is blocked' do
|
||||
before do
|
||||
current_user.block
|
||||
end
|
||||
|
||||
context 'with user is blocked' do
|
||||
before do
|
||||
current_user.block
|
||||
end
|
||||
|
||||
it_behaves_like 'unauthorized'
|
||||
it 'returns 404' do
|
||||
expect_404_response(go)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -159,7 +177,7 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
end
|
||||
|
||||
context 'with api scope' do
|
||||
it_behaves_like 'authenticated'
|
||||
it_behaves_like 'when authenticated'
|
||||
end
|
||||
|
||||
context 'with read_user scope' do
|
||||
|
|
@ -167,7 +185,7 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
personal_access_token.update_attribute(:scopes, [:read_user])
|
||||
end
|
||||
|
||||
it_behaves_like 'unauthorized'
|
||||
it_behaves_like 'when invalid authentication header exists'
|
||||
end
|
||||
|
||||
context 'with a denylisted ip' do
|
||||
|
|
@ -249,23 +267,6 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
expect_404_response(go)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a non-standard head' do
|
||||
let(:user) { create(:user) }
|
||||
let!(:project) { create(:project, :public, :repository) }
|
||||
let(:path) { project.full_path }
|
||||
let(:default_branch) { 'default_branch' }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
project.repository.add_branch(user, default_branch, 'master')
|
||||
project.change_head(default_branch)
|
||||
end
|
||||
|
||||
it 'returns the full project path' do
|
||||
expect_response_with_path(go, enabled_protocol, project.full_path, default_branch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with SSH disabled' do
|
||||
|
|
@ -311,7 +312,7 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
expect(response[0]).to eq(404)
|
||||
end
|
||||
|
||||
def expect_response_with_path(response, protocol, path, branch)
|
||||
def expect_response_with_path(response, protocol, path, source_branch = nil)
|
||||
repository_url = case protocol
|
||||
when :ssh
|
||||
shell = Gitlab.config.gitlab_shell
|
||||
|
|
@ -322,7 +323,8 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
project_url = "http://#{Gitlab.config.gitlab.host}/#{path}"
|
||||
expect(response[0]).to eq(200)
|
||||
expect(response[1]['Content-Type']).to eq('text/html')
|
||||
expected_body = %(<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}"><meta name="go-source" content="#{Gitlab.config.gitlab.host}/#{path} #{project_url} #{project_url}/-/tree/#{branch}{/dir} #{project_url}/-/blob/#{branch}{/dir}/{file}#L{line}"></head><body>go get #{Gitlab.config.gitlab.host}/#{path}</body></html>)
|
||||
go_source = source_branch ? %(<meta name="go-source" content="#{Gitlab.config.gitlab.host}/#{path} #{project_url} #{project_url}/-/tree/#{source_branch}{/dir} #{project_url}/-/blob/#{source_branch}{/dir}/{file}#L{line}">) : ''
|
||||
expected_body = %(<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}">#{go_source}</head><body>go get #{Gitlab.config.gitlab.host}/#{path}</body></html>)
|
||||
expect(response[2]).to eq([expected_body])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
if $LOADED_FEATURES.include?(File.expand_path('../../spec_helper.rb', __dir__.to_s))
|
||||
# return if spec_helper is already loaded, so we don't accidentally override any configuration in it
|
||||
return
|
||||
end
|
||||
|
||||
require_relative '../../fast_spec_helper'
|
||||
require_relative '../../support/matchers/result_matchers'
|
||||
require_relative '../../support/railway_oriented_programming'
|
||||
|
||||
require 'rspec-parameterized'
|
||||
require 'json_schemer'
|
||||
require 'devfile'
|
||||
require 'gitlab/rspec/next_instance_of'
|
||||
|
||||
RSpec.configure do |config|
|
||||
# Ensure that all specs which require this fast_spec_helper have the `:rd_fast` tag at the top-level describe
|
||||
config.after(:suite) do
|
||||
RSpec.world.example_groups.each do |example_group|
|
||||
# Check only top-level describes
|
||||
next unless example_group.metadata[:parent_example_group].nil?
|
||||
|
||||
unless example_group.metadata[:rd_fast]
|
||||
raise "Top-level describe blocks must have the `:rd_fast` tag when `rd_fast_spec_helper` is required. " \
|
||||
"It is missing on example group: #{example_group.description}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Set up rspec features required by the remote development specs
|
||||
config.include NextInstanceOf
|
||||
config.mock_with :rspec do |mocks|
|
||||
mocks.verify_doubled_constant_names = false
|
||||
end
|
||||
end
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../rd_fast_spec_helper"
|
||||
require "fast_spec_helper"
|
||||
|
||||
RSpec.describe RemoteDevelopment::Settings::Main, :rd_fast, feature_category: :remote_development do
|
||||
RSpec.describe RemoteDevelopment::Settings::Main, feature_category: :remote_development do
|
||||
let(:settings) { 'some settings' }
|
||||
let(:context_passed_along_steps) { { settings: settings } }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../rd_fast_spec_helper"
|
||||
require "fast_spec_helper"
|
||||
|
||||
RSpec.describe RemoteDevelopment::Settings::ReconciliationIntervalSecondsValidator, :rd_fast, feature_category: :remote_development do
|
||||
RSpec.describe RemoteDevelopment::Settings::ReconciliationIntervalSecondsValidator, feature_category: :remote_development do
|
||||
include ResultMatchers
|
||||
|
||||
let(:context) do
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../rd_fast_spec_helper"
|
||||
require "fast_spec_helper"
|
||||
|
||||
RSpec.describe RemoteDevelopment::Settings::SettingsInitializer,
|
||||
:rd_fast, feature_category: :remote_development do
|
||||
feature_category: :remote_development do
|
||||
let(:all_possible_requested_setting_names) { RemoteDevelopment::Settings::DefaultSettings.default_settings.keys }
|
||||
let(:requested_setting_names) { all_possible_requested_setting_names }
|
||||
let(:context) do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'fast_spec_helper'
|
||||
|
||||
RSpec.describe RemoteDevelopment::Settings, :rd_fast, feature_category: :remote_development do
|
||||
RSpec.describe RemoteDevelopment::Settings, feature_category: :remote_development do
|
||||
let(:response_hash) { { settings: { some_setting: 42 }, status: :success } }
|
||||
let(:get_settings_args) { { requested_setting_names: [:some_setting], options: { some_option: 42 } } }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../web_ide_fast_spec_helper"
|
||||
require "fast_spec_helper"
|
||||
|
||||
RSpec.describe WebIde::Settings::ExtensionsGalleryMetadataGenerator, :web_ide_fast, feature_category: :web_ide do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../web_ide_fast_spec_helper"
|
||||
require "fast_spec_helper"
|
||||
|
||||
RSpec.describe WebIde::Settings::ExtensionsGalleryMetadataValidator, :web_ide_fast, feature_category: :web_ide do
|
||||
include ResultMatchers
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../web_ide_fast_spec_helper"
|
||||
require "fast_spec_helper"
|
||||
|
||||
RSpec.describe WebIde::Settings::ExtensionsGalleryValidator, :web_ide_fast, feature_category: :web_ide do
|
||||
include ResultMatchers
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../web_ide_fast_spec_helper"
|
||||
require "fast_spec_helper"
|
||||
|
||||
RSpec.describe WebIde::Settings::Main, :web_ide_fast, feature_category: :web_ide do
|
||||
let(:settings) { 'some settings' }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../web_ide_fast_spec_helper"
|
||||
require "fast_spec_helper"
|
||||
|
||||
RSpec.describe WebIde::Settings::SettingsInitializer, :web_ide_fast, feature_category: :web_ide do
|
||||
let(:all_possible_requested_setting_names) { WebIde::Settings::DefaultSettings.default_settings.keys }
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
if $LOADED_FEATURES.include?(File.expand_path('../../spec_helper.rb', __dir__.to_s))
|
||||
# return if spec_helper is already loaded, so we don't accidentally override any configuration in it
|
||||
return
|
||||
end
|
||||
|
||||
require_relative '../../fast_spec_helper'
|
||||
require_relative '../../support/matchers/result_matchers'
|
||||
require_relative '../../support/railway_oriented_programming'
|
||||
|
||||
require 'rspec-parameterized'
|
||||
require 'json_schemer'
|
||||
require 'gitlab/rspec/next_instance_of'
|
||||
|
||||
RSpec.configure do |config|
|
||||
# Set up rspec features required by the fast specs
|
||||
config.include NextInstanceOf
|
||||
config.mock_with :rspec do |mocks|
|
||||
mocks.verify_doubled_constant_names = false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'json_schemer'
|
||||
|
|
@ -1359,10 +1359,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.109.0.tgz#af953d8114768343034f1f02bc8e2d93eb613c65"
|
||||
integrity sha512-MmBTsco2LIh/l16iJQy6R98YDOlE3C++AE0Z1+KCpAX/3+fLAmULx2sWp+JnmM0ws8J0LaeLN6+vWiPaEWA16Q==
|
||||
|
||||
"@gitlab/ui@87.6.1":
|
||||
version "87.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-87.6.1.tgz#f6d9fad3689890d430fe179e3d58f8e75f00369e"
|
||||
integrity sha512-5Vfl64zrJaXAeJDrPNtpv5yFygGqceucJb4Fe8RvMEiY9fbSwnwlU22BAv45b5mWEiY/C3wsURLDwNw16Xt2pg==
|
||||
"@gitlab/ui@87.7.0":
|
||||
version "87.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-87.7.0.tgz#2d84a38e3395d9272446645689b3cce5455f2aec"
|
||||
integrity sha512-g0dV7+2g3kkzyCWqeM/yrzJ8/lP4MvfBV5WkoxZMR1n6ux75QalhmTyKyBGayN3K2nCsf3ynr748KBtdxRl5Mw==
|
||||
dependencies:
|
||||
"@floating-ui/dom" "1.4.3"
|
||||
echarts "^5.3.2"
|
||||
|
|
|
|||
Loading…
Reference in New Issue