Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
de288afc2f
commit
6c040cd502
|
|
@ -656,6 +656,11 @@
|
|||
- "lib/gitlab/audit/type/definition.rb"
|
||||
- "ee/lib/ee/gitlab/audit/type/definition.rb"
|
||||
|
||||
.custom-roles-patterns: &custom-roles-patterns
|
||||
- "ee/config/custom_abilities/*.yml"
|
||||
- "doc/user/custom_roles/abilities.md"
|
||||
- "tooling/custom_roles/docs/templates/custom_abilities.md.erb"
|
||||
|
||||
##################
|
||||
# Conditions set #
|
||||
##################
|
||||
|
|
@ -1197,6 +1202,16 @@
|
|||
- <<: *if-default-refs
|
||||
changes: *audit-events-patterns
|
||||
|
||||
############################
|
||||
# Custom roles rules #
|
||||
############################
|
||||
.custom-roles:rules:custom-roles-verify:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
when: never
|
||||
- <<: *if-default-refs
|
||||
changes: *custom-roles-patterns
|
||||
|
||||
##################
|
||||
# Frontend rules #
|
||||
##################
|
||||
|
|
|
|||
|
|
@ -200,6 +200,19 @@ audit-event-types-verify:
|
|||
script:
|
||||
- bundle exec rake gitlab:audit_event_types:check_docs
|
||||
|
||||
custom-roles-verify:
|
||||
variables:
|
||||
SETUP_DB: "false"
|
||||
extends:
|
||||
- .default-retry
|
||||
- .ruby-cache
|
||||
- .default-before_script
|
||||
- .custom-roles:rules:custom-roles-verify
|
||||
stage: lint
|
||||
needs: []
|
||||
script:
|
||||
- bundle exec rake gitlab:custom_roles:check_docs
|
||||
|
||||
templates-shellcheck:
|
||||
extends:
|
||||
- .ci-templates:rules:shellcheck
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
076bbe2525323fa920885350e0e81d81b2f58cf6
|
||||
131b6727764a79bfe84c172b06aa4897230c805f
|
||||
|
|
|
|||
|
|
@ -1074,7 +1074,7 @@ This file is located at:
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Premium, Ultimate
|
||||
**Offering:** Self-Managed, SaaS
|
||||
**Offering:** Saas, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120506) in GitLab 16.9.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,11 @@ info: Any user with at least the Maintainer role can merge updates to this conte
|
|||
|
||||
## Set up GitLab Duo Chat
|
||||
|
||||
NOTE:
|
||||
Use [this snippet](https://gitlab.com/gitlab-org/gitlab/-/snippets/2554994) for help automating the following section.
|
||||
There is a difference in the setup for Saas and self-managed instances.
|
||||
We recommend to start with a process described for SaaS-only AI features.
|
||||
|
||||
1. [Enable Anthropic API features](index.md#configure-anthropic-access).
|
||||
1. [Ensure the embedding database is configured](index.md#embeddings-database).
|
||||
1. Ensure that your current branch is up-to-date with `master`.
|
||||
1. Enable the feature in Rails console: `Feature.enable(:tanuki_bot_breadcrumbs_entry_point)`
|
||||
1. [Setup SaaS-only AI features](index.md#test-saas-only-ai-features-locally).
|
||||
1. [Setup self-managed AI features](index.md#test-ai-features-with-ai-gateway-locally).
|
||||
|
||||
## Working with GitLab Duo Chat
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ info: Any user with at least the Maintainer role can merge updates to this conte
|
|||
|
||||
Apply the following feature flags to any AI feature work:
|
||||
|
||||
- A general flag (`ai_duo_chat_switch`) that applies to all GitLab Duo Chat features.
|
||||
- A general flag (`ai_global_switch`) that applies to all other AI features.
|
||||
- A general flag (`ai_duo_chat_switch`) that applies to all GitLab Duo Chat features. It's enabled by default.
|
||||
- A general flag (`ai_global_switch`) that applies to all other AI features. It's enabled by default.
|
||||
- A flag specific to that feature. The feature flag name [must be different](../feature_flags/index.md#feature-flags-for-licensed-features) than the licensed feature name.
|
||||
|
||||
See the [feature flag tracker epic](https://gitlab.com/groups/gitlab-org/-/epics/10524) for the list of all feature flags and how to use them.
|
||||
|
|
@ -55,33 +55,51 @@ See [below](#test-ai-features-with-ai-gateway-locally)
|
|||
|
||||
## Test SaaS-only AI features locally
|
||||
|
||||
**One-line setup**
|
||||
**Automated setup**
|
||||
|
||||
Replace`<test-group-name>` with the group name you want to enable GitLab Duo features.
|
||||
If the group doesn't exist, it creates a new one.
|
||||
You might need to re-run the script multiple times,
|
||||
it will print useful error messages with links to the docs on how to resolve the error.
|
||||
|
||||
```shell
|
||||
# Replace the <test-group-name> by the group name you want to enable GitLab Duo features. If the group doesn't exist, it creates a new one.
|
||||
RAILS_ENV=development bundle exec rake gitlab:duo:setup['<test-group-name>']
|
||||
GITLAB_SIMULATE_SAAS=1 RAILS_ENV=development bundle exec rake 'gitlab:duo:setup[<test-group-name>]'
|
||||
```
|
||||
|
||||
**Manual way**
|
||||
|
||||
1. Enable the required general feature flags:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:ai_duo_chat_switch, type: :ops)
|
||||
Feature.enable(:ai_global_switch, type: :ops)
|
||||
```
|
||||
|
||||
1. Ensure you have followed [the process to obtain an EE license](https://handbook.gitlab.com/handbook/developer-onboarding/#working-on-gitlab-ee-developer-licenses) for your local instance and you applied this license.
|
||||
1. Simulate the GDK to [simulate SaaS](../ee_features.md#simulate-a-saas-instance) and ensure the group you want to test has an Ultimate license
|
||||
1. Enable `Experiment & Beta features`
|
||||
1. Ensure you have followed [the process to obtain an EE license](https://handbook.gitlab.com/handbook/developer-onboarding/#working-on-gitlab-ee-developer-licenses) for your local instance and you applied Ultimate license.
|
||||
1. To verify that the license is applied go to **Admin Area** > **Subscription** and check the subscription plan.
|
||||
1. Allow use of EE features for your instance.
|
||||
1. Go to **Admin Area** > **Settings** > **General** -> **Account and limit**
|
||||
1. Enable **Allow use of licensed EE features**
|
||||
1. Simulate the GDK to [simulate SaaS](../ee_features.md#simulate-a-saas-instance).
|
||||
1. Ensure the group you want to test has an Ultimate license.
|
||||
1. Go to **Admin Area** > **Overview** > **Groups**
|
||||
1. Select **Edit** for your chosen group.
|
||||
1. Go to **Permissions and group features**
|
||||
1. Choose *Ultimate* from the **Plan** list.
|
||||
1. Enable `Experiment & Beta features` for your group.
|
||||
1. Go to the group with the Ultimate license
|
||||
1. **Group Settings** > **General** -> **Permissions and group features**
|
||||
1. Enable **Experiment & Beta features**
|
||||
1. Enable the specific feature flag for the feature you want to test
|
||||
1. You can use Rake task `rake gitlab:duo:enable_feature_flags` to enable all feature flags that are assigned to group AI Framework
|
||||
1. Setup [AI Gateway](#test-ai-features-with-ai-gateway-locally)
|
||||
|
||||
### Temporary workaround to avoid AI Gateway setup
|
||||
|
||||
NOTE:
|
||||
You need to setup AI Gateway since GitLab 16.8.
|
||||
It's a recommended way to test AI features. Sending requests directly to LLMs could lead to unnoticed bugs.
|
||||
Use this workaround with caution.
|
||||
|
||||
To setup direct requests to LLMs you have to:
|
||||
|
||||
1. Disable a feature flag `gitlab_duo_chat_requests_to_ai_gateway`.
|
||||
1. Set the required access token. To receive an access token:
|
||||
1. For Vertex, follow the [instructions below](#configure-gcp-vertex-access).
|
||||
1. For Anthropic, create an access request
|
||||
1. For Anthropic, create [an access request](https://gitlab.com/gitlab-com/team-member-epics/access-requests/-/issues/new).
|
||||
|
||||
### Configure GCP Vertex access
|
||||
|
||||
|
|
|
|||
|
|
@ -864,8 +864,9 @@ See also:
|
|||
|
||||
## GitLab SaaS
|
||||
|
||||
Use **GitLab SaaS** to refer to the product offering.
|
||||
It does not refer to the GitLab instance, which is [GitLab.com](#gitlabcom).
|
||||
**GitLab SaaS** refers to both [GitLab.com](#gitlabcom) (multi-tenant SaaS) as well as [GitLab Dedicated](#gitlab-dedicated) (single-tenant SaaS).
|
||||
|
||||
Try to avoid **GitLab SaaS** and instead, refer to the [specific offering](#offerings) instead.
|
||||
|
||||
## GitLab self-managed
|
||||
|
||||
|
|
@ -873,7 +874,7 @@ Use **GitLab self-managed** to refer to the product offering. It refers to a Git
|
|||
|
||||
## GitLab.com
|
||||
|
||||
Use **GitLab.com** to refer to the URL. GitLab.com is the instance that's managed by GitLab.
|
||||
Use **GitLab.com** to refer to the URL or product offering. GitLab.com is the instance that's managed by GitLab.
|
||||
|
||||
## guide
|
||||
|
||||
|
|
@ -1287,7 +1288,7 @@ Instead of:
|
|||
|
||||
The current product offerings are:
|
||||
|
||||
- [GitLab SaaS](#gitlab-saas)
|
||||
- [GitLab.com](#gitlabcom)
|
||||
- [GitLab self-managed](#gitlab-self-managed)
|
||||
- [GitLab Dedicated](#gitlab-dedicated)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Premium, Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
<!-- vale gitlab.FutureTense = NO -->
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
|
|
@ -0,0 +1,184 @@
|
|||
---
|
||||
stage: Plan
|
||||
group: Project Management
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Tutorial: Set up a single project for idea management
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Free, Premium, Ultimate
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
<!-- vale gitlab.FutureTense = NO -->
|
||||
|
||||
Idea management refers to the collection, organization, evaluation, and implementation of ideas
|
||||
within an organization or community.
|
||||
Ideas can originate from various stakeholders, such as employees, customers, or partners.
|
||||
|
||||
A separate idea backlog allows the team to capture and prioritize potential concepts and suggestions
|
||||
before they're fully fleshed out.
|
||||
Having this separate backlog enables efficient management of raw ideas.
|
||||
It does so without cluttering the main backlog with unrefined or not validated concepts.
|
||||
|
||||
In this tutorial, you'll learn how to set up a GitLab project for idea management.
|
||||
|
||||
To set up GitLab for idea management in a project:
|
||||
|
||||
1. [Create a project](#create-a-project)
|
||||
1. [Define the idea workflow](#define-the-idea-workflow)
|
||||
1. [Document your criteria](#document-your-criteria)
|
||||
1. [Create scoped labels](#create-scoped-labels)
|
||||
1. [Create an idea status board](#create-an-idea-status-board)
|
||||
1. [Stakeholders submit and vote on ideas](#stakeholders-submit-and-vote-on-ideas)
|
||||
1. [Triage new ideas](#triage-new-ideas)
|
||||
|
||||
## Before you begin
|
||||
|
||||
- If you're using an existing project for this tutorial, make sure you have at least the Reporter role
|
||||
for the project.
|
||||
- If you follow the steps below and later decide to create a
|
||||
parent group for your project, to make
|
||||
best use of labels, you'll have to promote the project labels to group labels.
|
||||
|
||||
## Create a project
|
||||
|
||||
A project contains the issues that will be used to track ideas.
|
||||
|
||||
To create a blank project:
|
||||
|
||||
1. On the left sidebar, at the top, select **Create new** (**{plus}**) and **New project/repository**.
|
||||
1. Select **Create blank project**.
|
||||
1. Enter the project details.
|
||||
- For **Project name**, enter `Idea management tutorial`.
|
||||
1. Select **Create project**.
|
||||
|
||||
## Define the idea workflow
|
||||
|
||||
Next, you'll need to determine the **status workflow** that ideas will follow.
|
||||
Communicating the status of an idea helps set the correct expectations with stakeholders.
|
||||
|
||||
For this tutorial, suppose you've decided on the following status workflow:
|
||||
|
||||
- `In Review`
|
||||
- `Backlog`
|
||||
- `In Progress`
|
||||
- `Complete`
|
||||
- `Rejected`
|
||||
|
||||
## Document your criteria
|
||||
|
||||
After you agree on the status workflow, write it all down somewhere your team mates can always access.
|
||||
|
||||
For example, add it to a [wiki](../../user/project/wiki/index.md) in your project, or your company
|
||||
handbook published with [GitLab Pages](../../user/project/pages/index.md).
|
||||
|
||||
<!-- Idea for expanding this tutorial:
|
||||
Add steps for [creating a wiki page](../../user/project/wiki/index.md#create-a-new-wiki-page). -->
|
||||
|
||||
## Create scoped labels
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Premium, Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
|
||||
Next, you'll create labels to add to ideas to represent the status workflow.
|
||||
|
||||
The best tool for this is [scoped labels](../../user/project/labels.md#scoped-labels), which you
|
||||
can use to set mutually exclusive attributes.
|
||||
|
||||
Checking with the list of statuses you've assembled
|
||||
[previously](#define-the-idea-workflow), you'll want to create matching
|
||||
scoped labels.
|
||||
|
||||
The double colon (`::`) in the name of a scoped label prevents two labels of the same scope being
|
||||
used together.
|
||||
For example, if you add the `status::backlog` label to an issue that already has `status::in review`, the
|
||||
previous one is removed.
|
||||
|
||||
NOTE:
|
||||
Scoped labels are available in the Premium and Ultimate tier.
|
||||
If you're on the Free tier, you can use regular labels instead.
|
||||
However, they aren't mutually exclusive.
|
||||
|
||||
To create each label:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Manage > Labels**.
|
||||
1. Select **New label**.
|
||||
1. In the **Title** field, enter the name of the label. Start with `status::in review`.
|
||||
1. Optional. Select a color by selecting from the available colors, or enter a hex color value for
|
||||
a specific color in the **Background color** field.
|
||||
1. Select **Create label**.
|
||||
|
||||
Repeat these steps to create all the labels you'll need:
|
||||
|
||||
- `status::backlog`
|
||||
- `status::in progress`
|
||||
- `status::complete`
|
||||
- `status::rejected`
|
||||
|
||||
## Create an idea status board
|
||||
|
||||
To prepare for the incoming ideas, create an [issue board](../../user/project/issue_board.md) that organizes ideas by label.
|
||||
You'll use it to quickly create issues and add labels to them by dragging cards to various lists.
|
||||
|
||||
To set up your issue board:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your
|
||||
**Idea management tutorial** project.
|
||||
1. Select **Plan > Issue boards**.
|
||||
1. In the upper-left corner of the issue board page, select the dropdown list with the current board name.
|
||||
1. Select **Create new board**.
|
||||
1. In the **Title field**, enter `Idea status workflow`.
|
||||
1. Keep the **Show the Open list** checkbox selected and clear the **Show the Closed list** one.
|
||||
1. Select **Create board**. You should see an empty board.
|
||||
1. Create a list for the `status::in review` label:
|
||||
1. In the upper-left corner of the issue board page, select **Create list**.
|
||||
1. In the column that appears, from the **Value** dropdown list, select the `status::in review` label.
|
||||
1. Select **Add to board**.
|
||||
1. Repeat the previous step for labels `status::backlog`, `status::in progress`, `status::complete`, and `status::rejected`.
|
||||
|
||||
For now, the lists in your board should be empty. Next, you'll populate them with some issues.
|
||||
|
||||

|
||||
|
||||
## Stakeholders submit and vote on ideas
|
||||
|
||||
Share your idea management project with stakeholders and invite them to document their ideas!
|
||||
|
||||
To invite your stakeholders:
|
||||
|
||||
1. On the left sidebar, select **Manage > Members**
|
||||
1. Select **Invite members**
|
||||
1. Type your stakeholders email address.
|
||||
1. Select **Reporter** role.
|
||||
|
||||
Your stakeholders can now access your project to create new ideas:
|
||||
|
||||
1. On the left sidebar, select **Plan > Issues**
|
||||
1. On the top right, select **New issue**
|
||||
1. Enter a title and description.
|
||||
1. Select **Create issue**
|
||||
|
||||
Stakeholders can also upvote an existing idea to signal that they are interested in an idea:
|
||||
|
||||
1. On the left sidebar, select **Plan > Issues**.
|
||||
1. Select an issue.
|
||||
1. Select the **Thumbs up** [emoji reaction](../../user/emoji_reactions.md) under the issue description.
|
||||
|
||||
## Triage new ideas
|
||||
|
||||
Try it out by dragging some issues from the **Open** list to one of the label lists to set the workflow status.
|
||||
|
||||

|
||||
|
||||
## Next steps
|
||||
|
||||
Next, you can:
|
||||
|
||||
- Create an [issue template](../../user/project/description_templates.md) to gather all the important
|
||||
details from your stakeholders.
|
||||
- Use [comments and threads](../../user/discussions/index.md) to gather more information about an idea.
|
||||
- [Relate](../../user/project/issues/related_issues.md) issues in your team backlog to issues in your
|
||||
idea project.
|
||||
|
|
@ -87,7 +87,7 @@ handbook published with [GitLab Pages](../../user/project/pages/index.md).
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Premium, Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
Next, you'll create labels to add to issues to categorize them.
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ issues, epics, and more.
|
|||
| [GitLab Agile Project Management](https://levelup.gitlab.com/courses/gitlab-agile-project-management-s2) | Learn how to use planning features to manage your projects in this self-paced course. | **{star}** |
|
||||
| [Build a protected workflow for your project](protected_workflow/index.md) | Set up a workflow for your teams, and enforce protections with approval rules. | |
|
||||
| [Run an agile iteration](agile_sprint/index.md) | Use group, projects, and iterations to run an agile development iteration. | |
|
||||
| [Set up a single project for idea management](idea_management/index.md) | Use an issue board and scoped labels to manage ideas in a team. | **{star}** |
|
||||
| [Set up a single project for issue triage](issue_triage/index.md) | Use labels to set up a project for issue triage. | **{star}** |
|
||||
| [Set up issue boards for team hand-off](boards_for_teams/index.md) | Use issue boards and scoped labels to set up collaboration across many teams. | **{star}** |
|
||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Epics and issue boards](https://www.youtube.com/watch?v=eQUnHwbKEkY) | Find out how to use epics and issue boards for project management. | |
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ Some features are still in development. View details about [support for each sta
|
|||
- View [how to enable this setting](group/manage.md#enable-experiment-and-beta-features).
|
||||
- [Code Suggestions](project/repository/code_suggestions/index.md) is enabled when you purchase the
|
||||
GitLab Duo Pro add-on and assign seats to users.
|
||||
- [Chat](gitlab_duo_chat.md)
|
||||
- View [how to enable for self-managed](gitlab_duo_chat.md#for-self-managed-users).
|
||||
- View [how to enable for SaaS](gitlab_duo_chat.md#for-saas-users).
|
||||
|
||||
## Experimental AI features and how to use them
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
HTTP Archive (HAR) format files are an industry standard for exchanging information about HTTP
|
||||
requests and HTTP responses. A HAR file's content is JSON formatted, containing browser interactions
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
Web API fuzzing performs fuzz testing of API operation parameters. Fuzz testing sets operation
|
||||
parameters to unexpected values in an effort to cause unexpected behavior and errors in the API
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/9302) in GitLab 15.9. The API Discovery feature is in [Beta](../../../../policy/experiment-beta-support.md).
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
API Security refers to the measures taken to secure and protect web Application Programming Interfaces (APIs) from unauthorized access, misuse, and attacks.
|
||||
APIs are a crucial component of modern application development as they allow applications to interact with each other and exchange data.
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ You can configure the following security controls:
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
You can configure the following security controls:
|
||||
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variab
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
To allowlist specific vulnerabilities, follow these steps:
|
||||
|
||||
|
|
@ -804,7 +804,7 @@ After a vulnerability is found, you can [address it](../vulnerabilities/index.md
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
Some vulnerabilities can be fixed by applying the solution that GitLab
|
||||
automatically generates.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/371063) in GitLab 16.4 as an [Experiment](../../../policy/experiment-beta-support.md#experiment) with two [features flags](../../../administration/feature_flags.md) named `dependency_scanning_on_advisory_ingestion` and `package_metadata_advisory_sync`. Enabled by default.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/427424) in GitLab 16.7 with an additional feature flag named `global_dependency_scanning_on_advisory_ingestion`. Enabled by default.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
Coverage-guided fuzz testing sends random inputs to an instrumented version of your application in
|
||||
an effort to cause unexpected behavior. Such behavior indicates a bug that you should address.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
WARNING:
|
||||
**DO NOT** use credentials that are valid for production systems, production servers, or any that
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
The [logs](#read-the-logs) provide insight into what DAST is doing and expecting during the authentication process. For more detailed
|
||||
information, configure the [authentication report](#configure-the-authentication-report).
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
The following troubleshooting scenarios have been collected from customer support cases. If you
|
||||
experience a problem not addressed here, or the information here does not fix your problem, create a
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
WARNING:
|
||||
Proxy-based DAST was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/430966) in GitLab
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
WARNING:
|
||||
Do not run DAST scans against a production server. Not only can it perform *any* function that a user can, such
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
WARNING:
|
||||
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/430966) in GitLab 16.9 and will be removed in 17.0. Use [browser-based DAST](browser_based.md) instead. This change is a breaking change.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
For self-managed GitLab instances in an environment with limited, restricted, or intermittent access
|
||||
to external resources through the internet, some adjustments are required for the DAST job to
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> DAST API analyzer [became the default analyzer for on-demand DAST API scans](https://gitlab.com/groups/gitlab-org/-/epics/4254) in GitLab 15.6.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - System dependencies [introduced](https://gitlab.com/groups/gitlab-org/-/epics/6698) in GitLab 14.6.
|
||||
> - Group-level dependency list [introduced](https://gitlab.com/groups/gitlab-org/-/epics/8090) in GitLab 16.2 [with a flag](../../../administration/feature_flags.md) named `group_level_dependencies`. Disabled by default.
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ table.no-vertical-table-lines tr {
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
Dependency Scanning analyzes your application's dependencies for known vulnerabilities. All
|
||||
dependencies are scanned, including transitive dependencies, also known as nested dependencies.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
For an overview, see [Adopting GitLab application security](https://www.youtube.com/watch?v=5QlxkiKR04k).
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ Supported configuration formats:
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> Support for overriding rules [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) in GitLab 14.8.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
GitLab can check your application for security vulnerabilities including:
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab 14.4. Feature flag `security_orchestration_policies_configuration` removed.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - Group-level security policies [introduced](https://gitlab.com/groups/gitlab-org/-/epics/4425) in GitLab 15.2.
|
||||
> - Group-level security policies [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/356258) in GitLab 15.4.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - Group-level scan result policies [introduced](https://gitlab.com/groups/gitlab-org/-/epics/7622) in GitLab 15.6.
|
||||
> - Scan result policies feature was renamed to merge request approval policies in GitLab 16.9.
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ content directly. Instead, it enhances the results with additional properties, i
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
## Transition to Semgrep-based scanning
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235382) in GitLab 13.5.
|
||||
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ the repository. For details on the Solution format, see the Microsoft reference
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - Introduced for Ruby in GitLab 14.2.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/378622) for Go in GitLab 15.8.
|
||||
|
|
@ -153,7 +153,7 @@ False positive detection is available in a subset of the [supported languages](#
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5144) in GitLab 14.2.
|
||||
|
||||
|
|
@ -269,7 +269,7 @@ The [SAST report file](#output) is processed by GitLab and the details are shown
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
SAST results display in the merge request widget area if a report from the target
|
||||
branch is available for comparison. The merge request widget displays SAST results and resolutions that
|
||||
|
|
@ -281,7 +281,7 @@ were introduced by the changes made in the merge request.
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/10959) in GitLab 16.6 with a [flag](../../../administration/feature_flags.md) named `sast_reports_in_inline_diff`. Disabled by default.
|
||||
> - Enabled by default in GitLab 16.8.
|
||||
|
|
@ -341,7 +341,7 @@ The method you can use depends on your GitLab license tier.
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/410013) individual SAST analyzers configuration options from the UI in GitLab 16.2.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Free, Premium, Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
GitLab SAST uses a set of [analyzers](analyzers.md) to scan code for potential vulnerabilities.
|
||||
Each analyzer processes the code then uses rules to find possible weaknesses in source code.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6.
|
||||
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ To enable full history Secret Detection, set the variable `SECRET_DETECTION_HIST
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211387) in GitLab 13.5.
|
||||
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for passthrough chains.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
## Security Dashboards
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
When working with application security features, you might encounter the following issues.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
Each vulnerability in a project has a vulnerability page containing details of the vulnerability,
|
||||
including:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
GitLab vulnerability analyzers attempt to return vulnerability severity level values whenever
|
||||
possible. The following is a list of available GitLab vulnerability severity levels, ranked from
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
The Vulnerability Report provides information about vulnerabilities from scans of the default branch. It contains
|
||||
cumulative results of all successful jobs, regardless of whether the pipeline was successful. The scan results from a
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Free, Premium, Ultimate
|
||||
**Offering:** self-managed
|
||||
**Offering:** Self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840) in GitLab 11.11.
|
||||
> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ Custom project templates are available at:
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13756) in GitLab 12.10
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in GitLab 12.0.
|
||||
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ You can [review recently triggered webhook payloads](#troubleshooting) in GitLab
|
|||
## Configure webhooks to support mutual TLS
|
||||
|
||||
DETAILS:
|
||||
**Offering:** self-managed
|
||||
**Offering:** Self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27450) in GitLab 16.9.
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,7 @@ merge request again.
|
|||
## Rebase a merge request from the Rails console
|
||||
|
||||
DETAILS:
|
||||
**tier:** Free, Premium, Ultimate
|
||||
**Offering:** Self-managed
|
||||
**Tier:** Free, Premium, Ultimate
|
||||
|
||||
In addition to the `/rebase` [quick action](../quick_actions.md#issues-merge-requests-and-epics),
|
||||
users with access to the [Rails console](../../../administration/operations/rails_console.md)
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ and set **Maintainer** in the **Allowed to create** column.
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259703) in GitLab Premium 13.9.
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ Evidence collection snapshots are visible on the Releases page, along with the t
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32773) in GitLab 13.2.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** SaaS, Self-managed
|
||||
**Offering:** SaaS, self-managed
|
||||
|
||||
NOTE:
|
||||
In 14.4, Requirements was moved under **Issues**.
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@ pre-push:
|
|||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: '{config/audit_events/types/*.yml,ee/config/audit_events/types/*yml,doc/administration/audit_event_types.md,tooling/audit_events/docs/templates/audit_event_types.md.erb}'
|
||||
run: bundle exec rake gitlab:audit_event_types:check_docs
|
||||
custom_roles_docs:
|
||||
tags: documentation
|
||||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: '{ee/config/custom_abilities/*yml,doc/user/custom_roles/abilities.md,tooling/custom_roles/docs/templates/custom_abilities.md.erb}'
|
||||
run: bundle exec rake gitlab:custom_roles:check_docs
|
||||
rubocop:
|
||||
tags: backend style
|
||||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ RSpec.describe '.gitlab/ci/rules.gitlab-ci.yml', feature_category: :tooling do
|
|||
# Ignore EE-only patterns list when in FOSS context
|
||||
relevant_patterns = foss_context ? patterns.reject { |pattern| pattern =~ %r|^{?ee/| } : patterns
|
||||
next if relevant_patterns.empty?
|
||||
next if foss_context && name == '.custom-roles-patterns'
|
||||
|
||||
PatternsList.new(name, relevant_patterns)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { GlDropdownItem, GlSorting, GlFilteredSearch, GlFormCheckbox } from '@gitlab/ui';
|
||||
import { shallowMount, mount } from '@vue/test-utils';
|
||||
|
||||
import { nextTick } from 'vue';
|
||||
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
||||
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
|
||||
import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
|
||||
import {
|
||||
|
|
@ -34,45 +36,39 @@ jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils', (
|
|||
).filterEmptySearchTerm,
|
||||
}));
|
||||
|
||||
const createComponent = ({
|
||||
shallow = true,
|
||||
namespace = 'gitlab-org/gitlab-test',
|
||||
recentSearchesStorageKey = 'requirements',
|
||||
tokens = mockAvailableTokens,
|
||||
sortOptions,
|
||||
initialSortBy,
|
||||
initialFilterValue = [],
|
||||
showCheckbox = false,
|
||||
checkboxChecked = false,
|
||||
searchInputPlaceholder = 'Filter requirements',
|
||||
} = {}) => {
|
||||
const mountMethod = shallow ? shallowMount : mount;
|
||||
|
||||
return mountMethod(FilteredSearchBarRoot, {
|
||||
propsData: {
|
||||
namespace,
|
||||
recentSearchesStorageKey,
|
||||
tokens,
|
||||
sortOptions,
|
||||
initialSortBy,
|
||||
initialFilterValue,
|
||||
showCheckbox,
|
||||
checkboxChecked,
|
||||
searchInputPlaceholder,
|
||||
},
|
||||
});
|
||||
const defaultProps = {
|
||||
namespace: 'gitlab-org/gitlab-test',
|
||||
recentSearchesStorageKey: 'requirements',
|
||||
tokens: mockAvailableTokens,
|
||||
initialFilterValue: [],
|
||||
showCheckbox: false,
|
||||
checkboxChecked: false,
|
||||
searchInputPlaceholder: 'Filter requirements',
|
||||
};
|
||||
|
||||
describe('FilteredSearchBarRoot', () => {
|
||||
useLocalStorageSpy();
|
||||
let wrapper;
|
||||
|
||||
const createComponent = ({ shallow = true, propsData = {} } = {}) => {
|
||||
const mountMethod = shallow ? shallowMount : mount;
|
||||
|
||||
wrapper = mountMethod(FilteredSearchBarRoot, { propsData: { ...defaultProps, ...propsData } });
|
||||
};
|
||||
|
||||
const findGlSorting = () => wrapper.findComponent(GlSorting);
|
||||
const findGlFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
|
||||
const findGlFormCheckbox = () => wrapper.findComponent(GlFormCheckbox);
|
||||
const findGlDropdownItem = () => wrapper.findComponent(GlDropdownItem);
|
||||
|
||||
afterEach(() => {
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
describe('data', () => {
|
||||
describe('when `sortOptions` are provided', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({ sortOptions: mockSortOptions });
|
||||
createComponent({ propsData: { sortOptions: mockSortOptions } });
|
||||
});
|
||||
|
||||
it('sets a correct initial value for GlFilteredSearch', () => {
|
||||
|
|
@ -95,7 +91,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
});
|
||||
|
||||
it('does not initialize the sort dropdown when `sortOptions` are not provided', () => {
|
||||
wrapper = createComponent();
|
||||
createComponent();
|
||||
|
||||
expect(findGlSorting().exists()).toBe(false);
|
||||
});
|
||||
|
|
@ -104,6 +100,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
describe('computed', () => {
|
||||
describe('tokenSymbols', () => {
|
||||
it('returns a map containing type and symbols from `tokens` prop', () => {
|
||||
createComponent();
|
||||
expect(wrapper.vm.tokenSymbols).toEqual({
|
||||
[TOKEN_TYPE_AUTHOR]: '@',
|
||||
[TOKEN_TYPE_LABEL]: '~',
|
||||
|
|
@ -114,6 +111,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('tokenTitles', () => {
|
||||
it('returns a map containing type and title from `tokens` prop', () => {
|
||||
createComponent();
|
||||
expect(wrapper.vm.tokenTitles).toEqual({
|
||||
[TOKEN_TYPE_AUTHOR]: 'Author',
|
||||
[TOKEN_TYPE_LABEL]: 'Label',
|
||||
|
|
@ -124,7 +122,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('sortDirectionIcon', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({ sortOptions: mockSortOptions });
|
||||
createComponent({ propsData: { sortOptions: mockSortOptions } });
|
||||
});
|
||||
|
||||
it('passes isAscending=false to GlSorting by default', () => {
|
||||
|
|
@ -141,7 +139,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('filteredRecentSearches', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent();
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('returns array of recent searches filtering out any string type (unsupported) items', async () => {
|
||||
|
|
@ -187,7 +185,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('events', () => {
|
||||
it('emits component event `onFilter` with empty array and true when initially selected filter value was cleared', async () => {
|
||||
wrapper = createComponent({ initialFilterValue: [tokenValueLabel] });
|
||||
createComponent({ propsData: { initialFilterValue: [tokenValueLabel] } });
|
||||
|
||||
wrapper.findComponent(GlFilteredSearch).vm.$emit('clear');
|
||||
|
||||
|
|
@ -199,15 +197,16 @@ describe('FilteredSearchBarRoot', () => {
|
|||
describe('methods', () => {
|
||||
describe('setupRecentSearch', () => {
|
||||
it('initializes `recentSearchesService` and `recentSearchesStore` props when `recentSearchesStorageKey` is available', () => {
|
||||
createComponent();
|
||||
expect(wrapper.vm.recentSearchesService instanceof RecentSearchesService).toBe(true);
|
||||
expect(wrapper.vm.recentSearchesStore instanceof RecentSearchesStore).toBe(true);
|
||||
});
|
||||
|
||||
it('initializes `recentSearchesPromise` prop with a promise by using `recentSearchesService.fetch()`', () => {
|
||||
jest.spyOn(wrapper.vm.recentSearchesService, 'fetch').mockResolvedValue([]);
|
||||
|
||||
wrapper.vm.setupRecentSearch();
|
||||
expect(localStorage.setItem).not.toHaveBeenCalled();
|
||||
createComponent();
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith('canUseLocalStorage', 'true');
|
||||
expect(wrapper.vm.recentSearchesPromise instanceof Promise).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -216,6 +215,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
const mockFilters = [tokenValueAuthor, tokenValueLabel, tokenValueConfidential, 'foo'];
|
||||
|
||||
it('returns filter array with unescaped strings for values which have spaces', () => {
|
||||
createComponent();
|
||||
expect(wrapper.vm.removeQuotesEnclosure(mockFilters)).toEqual([
|
||||
tokenValueAuthor,
|
||||
tokenValueLabel,
|
||||
|
|
@ -227,7 +227,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('handleSortOptionChange', () => {
|
||||
it('emits component event `onSort` with selected sort by value', async () => {
|
||||
wrapper = createComponent({ sortOptions: mockSortOptions });
|
||||
createComponent({ propsData: { sortOptions: mockSortOptions } });
|
||||
|
||||
findGlSorting().vm.$emit('sortByChange', mockSortOptions[1].id);
|
||||
await nextTick();
|
||||
|
|
@ -239,9 +239,11 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('handleSortDirectionChange', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({
|
||||
sortOptions: mockSortOptions,
|
||||
initialSortBy: mockSortOptions[0].sortDirection.descending,
|
||||
createComponent({
|
||||
propsData: {
|
||||
sortOptions: mockSortOptions,
|
||||
initialSortBy: mockSortOptions[0].sortDirection.descending,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -263,24 +265,27 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('handleHistoryItemSelected', () => {
|
||||
it('emits `onFilter` event with provided filters param', () => {
|
||||
jest.spyOn(wrapper.vm, 'removeQuotesEnclosure');
|
||||
|
||||
wrapper.vm.handleHistoryItemSelected(mockHistoryItems[0]);
|
||||
|
||||
createComponent();
|
||||
expect(wrapper.emitted('onFilter')).toEqual(undefined);
|
||||
findGlFilteredSearch().vm.$emit('history-item-selected', mockHistoryItems[0]);
|
||||
expect(wrapper.emitted('onFilter')[0]).toEqual([mockHistoryItems[0]]);
|
||||
expect(wrapper.vm.removeQuotesEnclosure).toHaveBeenCalledWith(mockHistoryItems[0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleClearHistory', () => {
|
||||
it('clears search history from recent searches store', () => {
|
||||
createComponent();
|
||||
jest.spyOn(wrapper.vm.recentSearchesStore, 'setRecentSearches').mockReturnValue([]);
|
||||
jest.spyOn(wrapper.vm.recentSearchesService, 'save');
|
||||
|
||||
wrapper.vm.handleClearHistory();
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(2);
|
||||
findGlFilteredSearch().vm.$emit('clear-history');
|
||||
|
||||
expect(wrapper.vm.recentSearchesStore.setRecentSearches).toHaveBeenCalledWith([]);
|
||||
expect(wrapper.vm.recentSearchesService.save).toHaveBeenCalledWith([]);
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(4);
|
||||
expect(localStorage.setItem).toHaveBeenLastCalledWith(
|
||||
'gitlab-org/gitlab-test-requirements-recent-searches',
|
||||
'[]',
|
||||
);
|
||||
expect(wrapper.vm.recentSearches).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
|
@ -289,7 +294,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
const mockFilters = [tokenValueAuthor, 'foo'];
|
||||
|
||||
beforeEach(async () => {
|
||||
wrapper = createComponent();
|
||||
createComponent();
|
||||
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
|
@ -319,25 +324,27 @@ describe('FilteredSearchBarRoot', () => {
|
|||
});
|
||||
|
||||
it('calls `recentSearchesService.save` with array of searches', async () => {
|
||||
jest.spyOn(wrapper.vm.recentSearchesService, 'save');
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(4);
|
||||
findGlFilteredSearch().vm.$emit('submit');
|
||||
await waitForPromises();
|
||||
|
||||
wrapper.vm.handleFilterSubmit();
|
||||
|
||||
await nextTick();
|
||||
|
||||
return wrapper.vm.recentSearchesPromise.then(() => {
|
||||
expect(wrapper.vm.recentSearchesService.save).toHaveBeenCalledWith([mockFilters]);
|
||||
});
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(6);
|
||||
expect(localStorage.setItem).toHaveBeenLastCalledWith(
|
||||
'gitlab-org/gitlab-test-requirements-recent-searches',
|
||||
JSON.stringify([mockFilters]),
|
||||
);
|
||||
});
|
||||
|
||||
it('sets `recentSearches` data prop with array of searches', () => {
|
||||
jest.spyOn(wrapper.vm.recentSearchesService, 'save');
|
||||
it('sets `recentSearches` data prop with array of searches', async () => {
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(4);
|
||||
findGlFilteredSearch().vm.$emit('submit');
|
||||
await waitForPromises();
|
||||
|
||||
wrapper.vm.handleFilterSubmit();
|
||||
|
||||
return wrapper.vm.recentSearchesPromise.then(() => {
|
||||
expect(wrapper.vm.recentSearches).toEqual([mockFilters]);
|
||||
});
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(6);
|
||||
expect(localStorage.setItem).toHaveBeenLastCalledWith(
|
||||
'gitlab-org/gitlab-test-requirements-recent-searches',
|
||||
JSON.stringify([mockFilters]),
|
||||
);
|
||||
});
|
||||
|
||||
it('calls `blurSearchInput` method to remove focus from filter input field', () => {
|
||||
|
|
@ -349,20 +356,18 @@ describe('FilteredSearchBarRoot', () => {
|
|||
});
|
||||
|
||||
it('emits component event `onFilter` with provided filters param', async () => {
|
||||
jest.spyOn(wrapper.vm, 'removeQuotesEnclosure');
|
||||
|
||||
expect(wrapper.emitted('onFilter')).toEqual(undefined);
|
||||
findGlFilteredSearch().vm.$emit('submit');
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.emitted('onFilter')[0]).toEqual([mockFilters]);
|
||||
expect(wrapper.vm.removeQuotesEnclosure).toHaveBeenCalledWith(mockFilters);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders gl-filtered-search component', async () => {
|
||||
wrapper = createComponent();
|
||||
createComponent();
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
await wrapper.setData({
|
||||
|
|
@ -376,89 +381,70 @@ describe('FilteredSearchBarRoot', () => {
|
|||
expect(glFilteredSearchEl.props('historyItems')).toEqual(mockHistoryItems);
|
||||
});
|
||||
|
||||
it('renders checkbox when `showCheckbox` prop is true', () => {
|
||||
let wrapperWithCheckbox = createComponent({
|
||||
showCheckbox: true,
|
||||
});
|
||||
it('renders unchecked checkbox when `showCheckbox` prop is true', () => {
|
||||
createComponent({ propsData: { showCheckbox: true } });
|
||||
expect(findGlFormCheckbox().exists()).toBe(true);
|
||||
expect(findGlFormCheckbox().attributes('checked')).not.toBeDefined();
|
||||
});
|
||||
|
||||
expect(wrapperWithCheckbox.findComponent(GlFormCheckbox).exists()).toBe(true);
|
||||
expect(
|
||||
wrapperWithCheckbox.findComponent(GlFormCheckbox).attributes('checked'),
|
||||
).not.toBeDefined();
|
||||
|
||||
wrapperWithCheckbox.destroy();
|
||||
|
||||
wrapperWithCheckbox = createComponent({
|
||||
showCheckbox: true,
|
||||
checkboxChecked: true,
|
||||
});
|
||||
|
||||
expect(wrapperWithCheckbox.findComponent(GlFormCheckbox).attributes('checked')).toBe('true');
|
||||
|
||||
wrapperWithCheckbox.destroy();
|
||||
it('renders checked checkbox when `checkboxChecked` prop is true', () => {
|
||||
createComponent({ propsData: { showCheckbox: true, checkboxChecked: true } });
|
||||
expect(findGlFormCheckbox().attributes('checked')).toBe('true');
|
||||
});
|
||||
|
||||
it('renders search history items dropdown with formatting done using token symbols', async () => {
|
||||
const wrapperFullMount = createComponent({ sortOptions: mockSortOptions, shallow: false });
|
||||
wrapperFullMount.vm.recentSearchesStore.addRecentSearch(mockHistoryItems[0]);
|
||||
|
||||
createComponent({ propsData: { sortOptions: mockSortOptions }, shallow: false });
|
||||
wrapper.vm.recentSearchesStore.addRecentSearch(mockHistoryItems[0]);
|
||||
await nextTick();
|
||||
|
||||
const searchHistoryItemsEl = wrapperFullMount.findAll(
|
||||
const searchHistoryItemsEl = wrapper.findAll(
|
||||
'.gl-search-box-by-click-menu .gl-search-box-by-click-history-item',
|
||||
);
|
||||
|
||||
expect(searchHistoryItemsEl.at(0).text()).toBe(
|
||||
'Author := @rootLabel := ~bugMilestone := %v1.0"duo"',
|
||||
);
|
||||
|
||||
wrapperFullMount.destroy();
|
||||
});
|
||||
|
||||
describe('when token options have `title` attribute defined', () => {
|
||||
it('renders search history items using the provided `title` attribute', async () => {
|
||||
const wrapperFullMount = createComponent({
|
||||
sortOptions: mockSortOptions,
|
||||
tokens: [mockMembershipToken],
|
||||
createComponent({
|
||||
propsData: {
|
||||
sortOptions: mockSortOptions,
|
||||
tokens: [mockMembershipToken],
|
||||
},
|
||||
shallow: false,
|
||||
});
|
||||
|
||||
wrapperFullMount.vm.recentSearchesStore.addRecentSearch([tokenValueMembership]);
|
||||
|
||||
wrapper.vm.recentSearchesStore.addRecentSearch([tokenValueMembership]);
|
||||
await nextTick();
|
||||
|
||||
expect(wrapperFullMount.findComponent(GlDropdownItem).text()).toBe('Membership := Direct');
|
||||
|
||||
wrapperFullMount.destroy();
|
||||
expect(findGlDropdownItem().text()).toBe('Membership := Direct');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when token options have do not have `title` attribute defined', () => {
|
||||
it('renders search history items using the provided `value` attribute', async () => {
|
||||
const wrapperFullMount = createComponent({
|
||||
sortOptions: mockSortOptions,
|
||||
tokens: [mockMembershipTokenOptionsWithoutTitles],
|
||||
createComponent({
|
||||
propsData: {
|
||||
sortOptions: mockSortOptions,
|
||||
tokens: [mockMembershipTokenOptionsWithoutTitles],
|
||||
},
|
||||
shallow: false,
|
||||
});
|
||||
|
||||
wrapperFullMount.vm.recentSearchesStore.addRecentSearch([tokenValueMembership]);
|
||||
|
||||
wrapper.vm.recentSearchesStore.addRecentSearch([tokenValueMembership]);
|
||||
await nextTick();
|
||||
|
||||
expect(wrapperFullMount.findComponent(GlDropdownItem).text()).toBe('Membership := exclude');
|
||||
|
||||
wrapperFullMount.destroy();
|
||||
expect(findGlDropdownItem().text()).toBe('Membership := exclude');
|
||||
});
|
||||
});
|
||||
|
||||
it('renders sort dropdown component', () => {
|
||||
wrapper = createComponent({ sortOptions: mockSortOptions });
|
||||
createComponent({ propsData: { sortOptions: mockSortOptions } });
|
||||
|
||||
expect(findGlSorting().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders sort dropdown items', () => {
|
||||
wrapper = createComponent({ sortOptions: mockSortOptions });
|
||||
createComponent({ propsData: { sortOptions: mockSortOptions } });
|
||||
|
||||
const { sortOptions, sortBy } = findGlSorting().props();
|
||||
|
||||
|
|
@ -485,7 +471,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
};
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({ sortOptions: mockSortOptions });
|
||||
createComponent({ propsData: { sortOptions: mockSortOptions } });
|
||||
});
|
||||
|
||||
it('syncs filter value', async () => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'checks if the doc is up-to-date' do
|
||||
subject(:check_docs_task) { described_class.new(docs_dir, docs_path, template_erb_path).run }
|
||||
|
||||
shared_examples 'outputs an error' do
|
||||
before do
|
||||
stub_definitions
|
||||
end
|
||||
|
||||
it 'raises an error' do
|
||||
expect { check_docs_task }.to raise_error(SystemExit).and output(/#{error_message}/).to_stdout
|
||||
end
|
||||
end
|
||||
|
||||
context 'when custom_abilities.md is up to date' do
|
||||
it 'outputs success message after checking the documentation' do
|
||||
expect { check_docs_task }.to output(success_message).to_stdout
|
||||
end
|
||||
end
|
||||
|
||||
context 'when custom_abilities.md is updated manually' do
|
||||
before do
|
||||
File.write(docs_path, "Manually adding this line at the end of the custom_abilities.md", mode: 'a+')
|
||||
end
|
||||
|
||||
it 'raises an error' do
|
||||
expect { check_docs_task }.to raise_error(SystemExit).and output(/#{error_message}/).to_stdout
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an existing custom ability is removed' do
|
||||
let(:updated_definitions) { removed_definition }
|
||||
|
||||
it_behaves_like 'outputs an error'
|
||||
end
|
||||
|
||||
context 'when a new custom ability is added' do
|
||||
let(:updated_definitions) { added_definition }
|
||||
|
||||
it_behaves_like 'outputs an error'
|
||||
end
|
||||
|
||||
context 'when an existing audit event type is updated' do
|
||||
let(:updated_definitions) { updated_definition }
|
||||
|
||||
it_behaves_like 'outputs an error'
|
||||
end
|
||||
end
|
||||
|
|
@ -9,7 +9,9 @@ RSpec.describe Tasks::Gitlab::AuditEventTypes::CheckDocsTask, feature_category:
|
|||
let(:docs_path) { Rails.root.join(docs_dir, 'audit_event_types.md') }
|
||||
let(:template_erb_path) { Rails.root.join("tooling/audit_events/docs/templates/audit_event_types.md.erb") }
|
||||
|
||||
subject(:check_docs_task) { described_class.new(docs_dir, docs_path, template_erb_path) }
|
||||
let(:stub_definitions) do
|
||||
expect(Gitlab::Audit::Type::Definition).to receive(:definitions).and_return(updated_definitions)
|
||||
end
|
||||
|
||||
describe '#run' do
|
||||
before do
|
||||
|
|
@ -17,51 +19,34 @@ RSpec.describe Tasks::Gitlab::AuditEventTypes::CheckDocsTask, feature_category:
|
|||
Tasks::Gitlab::AuditEventTypes::CompileDocsTask.new(docs_dir, docs_path, template_erb_path).run
|
||||
end
|
||||
|
||||
context 'when audit_event_types.md is up to date' do
|
||||
it 'outputs success message after checking the documentation' do
|
||||
expect { subject.run }.to output("Audit event types documentation is up to date.\n").to_stdout
|
||||
end
|
||||
let(:new_audit_event) do
|
||||
{ new_audit_event: instance_double(Gitlab::Audit::Type::Definition,
|
||||
name: 'new_audit_event',
|
||||
description: 'some description',
|
||||
feature_category: 'audit_events',
|
||||
introduced_by_mr: 'https://mr',
|
||||
introduced_by_issue: 'https://issue',
|
||||
milestone: '16.0',
|
||||
saved_to_database: true,
|
||||
streamed: false
|
||||
) }
|
||||
end
|
||||
|
||||
context 'when audit_event_types.md is updated manually' do
|
||||
before do
|
||||
File.write(docs_path, "Manually adding this line at the end of the audit_event_types.md", mode: 'a+')
|
||||
end
|
||||
let(:added_definition) { Gitlab::Audit::Type::Definition.definitions.merge(new_audit_event) }
|
||||
let(:removed_definition) { Gitlab::Audit::Type::Definition.definitions.except(:feature_flag_created) }
|
||||
let(:updated_definition) do
|
||||
definitions = Gitlab::Audit::Type::Definition.definitions
|
||||
definitions[:feature_flag_created].attributes[:streamed] = false
|
||||
|
||||
it 'raises an error' do
|
||||
expected_output = "Audit event types documentation is outdated! Please update it " \
|
||||
"by running `bundle exec rake gitlab:audit_event_types:compile_docs`"
|
||||
|
||||
expect { subject.run }.to raise_error(SystemExit).and output(/#{expected_output}/).to_stdout
|
||||
end
|
||||
definitions
|
||||
end
|
||||
|
||||
context 'when an existing audit event type is removed' do
|
||||
let(:updated_definition) { Gitlab::Audit::Type::Definition.definitions.except(:feature_flag_created) }
|
||||
|
||||
it 'raises an error' do
|
||||
expect(Gitlab::Audit::Type::Definition).to receive(:definitions).and_return(updated_definition)
|
||||
|
||||
expected_output = "Audit event types documentation is outdated! Please update it " \
|
||||
"by running `bundle exec rake gitlab:audit_event_types:compile_docs`"
|
||||
|
||||
expect { subject.run }.to raise_error(SystemExit).and output(/#{expected_output}/).to_stdout
|
||||
end
|
||||
let(:success_message) { "Audit event types documentation is up to date.\n" }
|
||||
let(:error_message) do
|
||||
"Audit event types documentation is outdated! Please update it " \
|
||||
"by running `bundle exec rake gitlab:audit_event_types:compile_docs`"
|
||||
end
|
||||
|
||||
context 'when an existing audit event type is updated' do
|
||||
let(:updated_definition) { Gitlab::Audit::Type::Definition.definitions }
|
||||
|
||||
it 'raises an error' do
|
||||
updated_definition[:feature_flag_created].attributes[:streamed] = false
|
||||
|
||||
expect(Gitlab::Audit::Type::Definition).to receive(:definitions).and_return(updated_definition)
|
||||
|
||||
expected_output = "Audit event types documentation is outdated! Please update it " \
|
||||
"by running `bundle exec rake gitlab:audit_event_types:compile_docs`"
|
||||
|
||||
expect { subject.run }.to raise_error(SystemExit).and output(/#{expected_output}/).to_stdout
|
||||
end
|
||||
end
|
||||
it_behaves_like 'checks if the doc is up-to-date'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue