Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-08-02 15:09:58 +00:00
parent f3a2d44292
commit 948b3c5ace
43 changed files with 548 additions and 403 deletions

View File

@ -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:

View File

@ -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'

View File

@ -1 +1 @@
7472acfcaa3ee8406581e33a54c9949daef1a22e
0b93282f3ccd586a8916a0eddc3bc3b955654cc1

View File

@ -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>

View File

@ -17,9 +17,9 @@ export default {
default: null,
},
count: {
type: Number,
type: [String, Number],
required: false,
default: null,
default: '',
},
icon: {
type: String,

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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**.

View File

@ -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

View File

@ -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

View File

@ -1,7 +1,5 @@
# frozen_string_literal: true
require 'json_schemer'
module WebIde
module Settings
class ExtensionsGalleryValidator

View File

@ -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 ""

View File

@ -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",

View File

@ -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

View File

@ -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?

View File

@ -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();

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 } }

View File

@ -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

View File

@ -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

View File

@ -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 } } }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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' }

View File

@ -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 }

View File

@ -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

View File

@ -0,0 +1,3 @@
# frozen_string_literal: true
require 'json_schemer'

View File

@ -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"