summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-10-05 15:08:27 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-10-05 15:08:27 +0000
commitfd340cdc681ddc2eb7e0a8ba3ae1efd45a4b0168 (patch)
treed7c2bf6efcd2f1661f54f204e34e46b0b72788df
parent146284d119185475742085e35d34a702a05a6fc4 (diff)
downloadgitlab-ce-fd340cdc681ddc2eb7e0a8ba3ae1efd45a4b0168.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/index.js3
-rw-r--r--app/assets/javascripts/projects/settings/components/default_branch_selector.vue38
-rw-r--r--app/assets/javascripts/projects/settings/mount_default_branch_selector.js22
-rw-r--r--app/assets/javascripts/ref/components/ref_selector.vue174
-rw-r--r--app/views/projects/default_branch/_show.html.haml2
-rw-r--r--doc/development/database/batched_background_migrations.md16
-rw-r--r--doc/user/application_security/terminology/index.md87
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--qa/qa/page/project/settings/default_branch.rb14
-rw-r--r--spec/features/projects/settings/user_changes_default_branch_spec.rb13
-rw-r--r--spec/frontend/projects/settings/components/default_branch_selector_spec.js46
-rw-r--r--spec/frontend/ref/components/ref_selector_spec.js28
15 files changed, 340 insertions, 115 deletions
diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
index 655243eee30..d2263fa815d 100644
--- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
@@ -1,5 +1,7 @@
import MirrorRepos from '~/mirrors/mirror_repos';
import mountBranchRules from '~/projects/settings/repository/branch_rules/mount_branch_rules';
+import mountDefaultBranchSelector from '~/projects/settings/mount_default_branch_selector';
+
import initForm from '../form';
initForm();
@@ -8,3 +10,4 @@ const mirrorReposContainer = document.querySelector('.js-mirror-settings');
if (mirrorReposContainer) new MirrorRepos(mirrorReposContainer).init();
mountBranchRules(document.getElementById('js-branch-rules'));
+mountDefaultBranchSelector(document.querySelector('.js-select-default-branch'));
diff --git a/app/assets/javascripts/projects/settings/components/default_branch_selector.vue b/app/assets/javascripts/projects/settings/components/default_branch_selector.vue
new file mode 100644
index 00000000000..fee2f591216
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/components/default_branch_selector.vue
@@ -0,0 +1,38 @@
+<script>
+import RefSelector from '~/ref/components/ref_selector.vue';
+import { REF_TYPE_BRANCHES } from '~/ref/constants';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ RefSelector,
+ },
+ props: {
+ persistedDefaultBranch: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: String,
+ required: true,
+ },
+ },
+ refTypes: [REF_TYPE_BRANCHES],
+ i18n: {
+ dropdownHeader: __('Select default branch'),
+ searchPlaceholder: __('Search branch'),
+ },
+};
+</script>
+<template>
+ <ref-selector
+ :value="persistedDefaultBranch"
+ class="gl-w-full"
+ :project-id="projectId"
+ :enabled-ref-types="$options.refTypes"
+ :translations="$options.i18n"
+ name="project[default_branch]"
+ data-testid="default-branch-dropdown"
+ data-qa-selector="default_branch_dropdown"
+ />
+</template>
diff --git a/app/assets/javascripts/projects/settings/mount_default_branch_selector.js b/app/assets/javascripts/projects/settings/mount_default_branch_selector.js
new file mode 100644
index 00000000000..611561e38f2
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/mount_default_branch_selector.js
@@ -0,0 +1,22 @@
+import Vue from 'vue';
+import DefaultBranchSelector from './components/default_branch_selector.vue';
+
+export default (el) => {
+ if (!el) {
+ return null;
+ }
+
+ const { projectId, defaultBranch } = el.dataset;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(DefaultBranchSelector, {
+ props: {
+ persistedDefaultBranch: defaultBranch,
+ projectId,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/ref/components/ref_selector.vue b/app/assets/javascripts/ref/components/ref_selector.vue
index 1343ad8246c..b75958e2ced 100644
--- a/app/assets/javascripts/ref/components/ref_selector.vue
+++ b/app/assets/javascripts/ref/components/ref_selector.vue
@@ -29,6 +29,7 @@ export default {
GlLoadingIcon,
RefResultsSection,
},
+ inheritAttrs: false,
props: {
enabledRefTypes: {
type: Array,
@@ -70,6 +71,15 @@ export default {
required: false,
default: true,
},
+
+ /* Underlying form field name for scenarios where ref_selector
+ * is used as part of submitting an HTML form
+ */
+ name: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
@@ -213,89 +223,103 @@ export default {
</script>
<template>
- <gl-dropdown
- :header-text="i18n.dropdownHeader"
- :toggle-class="toggleButtonClass"
- :text="buttonText"
- class="ref-selector"
- v-bind="$attrs"
- v-on="$listeners"
- @shown="focusSearchBox"
- >
- <template #header>
- <gl-search-box-by-type
- ref="searchBox"
- v-model.trim="query"
- :placeholder="i18n.searchPlaceholder"
- autocomplete="off"
- @input="onSearchBoxInput"
- @keydown.enter.prevent="onSearchBoxEnter"
- />
- </template>
+ <div>
+ <gl-dropdown
+ :header-text="i18n.dropdownHeader"
+ :toggle-class="toggleButtonClass"
+ :text="buttonText"
+ class="ref-selector gl-w-full"
+ v-bind="$attrs"
+ v-on="$listeners"
+ @shown="focusSearchBox"
+ >
+ <template #header>
+ <gl-search-box-by-type
+ ref="searchBox"
+ v-model.trim="query"
+ :placeholder="i18n.searchPlaceholder"
+ autocomplete="off"
+ data-qa-selector="ref_selector_searchbox"
+ @input="onSearchBoxInput"
+ @keydown.enter.prevent="onSearchBoxEnter"
+ />
+ </template>
- <gl-loading-icon v-if="isLoading" size="lg" class="gl-my-3" />
+ <gl-loading-icon v-if="isLoading" size="lg" class="gl-my-3" />
- <div v-else-if="showNoResults" class="gl-text-center gl-mx-3 gl-py-3" data-testid="no-results">
- <gl-sprintf v-if="lastQuery" :message="i18n.noResultsWithQuery">
- <template #query>
- <b class="gl-word-break-all">{{ lastQuery }}</b>
- </template>
- </gl-sprintf>
+ <div
+ v-else-if="showNoResults"
+ class="gl-text-center gl-mx-3 gl-py-3"
+ data-testid="no-results"
+ >
+ <gl-sprintf v-if="lastQuery" :message="i18n.noResultsWithQuery">
+ <template #query>
+ <b class="gl-word-break-all">{{ lastQuery }}</b>
+ </template>
+ </gl-sprintf>
- <span v-else>{{ i18n.noResults }}</span>
- </div>
+ <span v-else>{{ i18n.noResults }}</span>
+ </div>
- <template v-else>
- <template v-if="showBranchesSection">
- <ref-results-section
- :section-title="i18n.branches"
- :total-count="matches.branches.totalCount"
- :items="matches.branches.list"
- :selected-ref="selectedRef"
- :error="matches.branches.error"
- :error-message="i18n.branchesErrorMessage"
- :show-header="showSectionHeaders"
- data-testid="branches-section"
- data-qa-selector="branches_section"
- @selected="selectRef($event)"
- />
+ <template v-else>
+ <template v-if="showBranchesSection">
+ <ref-results-section
+ :section-title="i18n.branches"
+ :total-count="matches.branches.totalCount"
+ :items="matches.branches.list"
+ :selected-ref="selectedRef"
+ :error="matches.branches.error"
+ :error-message="i18n.branchesErrorMessage"
+ :show-header="showSectionHeaders"
+ data-testid="branches-section"
+ data-qa-selector="branches_section"
+ @selected="selectRef($event)"
+ />
- <gl-dropdown-divider v-if="showTagsSection || showCommitsSection" />
- </template>
+ <gl-dropdown-divider v-if="showTagsSection || showCommitsSection" />
+ </template>
- <template v-if="showTagsSection">
- <ref-results-section
- :section-title="i18n.tags"
- :total-count="matches.tags.totalCount"
- :items="matches.tags.list"
- :selected-ref="selectedRef"
- :error="matches.tags.error"
- :error-message="i18n.tagsErrorMessage"
- :show-header="showSectionHeaders"
- data-testid="tags-section"
- @selected="selectRef($event)"
- />
+ <template v-if="showTagsSection">
+ <ref-results-section
+ :section-title="i18n.tags"
+ :total-count="matches.tags.totalCount"
+ :items="matches.tags.list"
+ :selected-ref="selectedRef"
+ :error="matches.tags.error"
+ :error-message="i18n.tagsErrorMessage"
+ :show-header="showSectionHeaders"
+ data-testid="tags-section"
+ @selected="selectRef($event)"
+ />
- <gl-dropdown-divider v-if="showCommitsSection" />
- </template>
+ <gl-dropdown-divider v-if="showCommitsSection" />
+ </template>
- <template v-if="showCommitsSection">
- <ref-results-section
- :section-title="i18n.commits"
- :total-count="matches.commits.totalCount"
- :items="matches.commits.list"
- :selected-ref="selectedRef"
- :error="matches.commits.error"
- :error-message="i18n.commitsErrorMessage"
- :show-header="showSectionHeaders"
- data-testid="commits-section"
- @selected="selectRef($event)"
- />
+ <template v-if="showCommitsSection">
+ <ref-results-section
+ :section-title="i18n.commits"
+ :total-count="matches.commits.totalCount"
+ :items="matches.commits.list"
+ :selected-ref="selectedRef"
+ :error="matches.commits.error"
+ :error-message="i18n.commitsErrorMessage"
+ :show-header="showSectionHeaders"
+ data-testid="commits-section"
+ @selected="selectRef($event)"
+ />
+ </template>
</template>
- </template>
- <template #footer>
- <slot name="footer" v-bind="footerSlotProps"></slot>
- </template>
- </gl-dropdown>
+ <template #footer>
+ <slot name="footer" v-bind="footerSlotProps"></slot>
+ </template>
+ </gl-dropdown>
+ <input
+ v-if="name"
+ data-testid="selected-ref-form-field"
+ type="hidden"
+ :value="selectedRef"
+ :name="name"
+ />
+ </div>
</template>
diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml
index eba0f336f80..23b46e02202 100644
--- a/app/views/projects/default_branch/_show.html.haml
+++ b/app/views/projects/default_branch/_show.html.haml
@@ -17,7 +17,7 @@
- else
.form-group
= f.label :default_branch, _("Default branch"), class: 'label-bold'
- = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide', data: { qa_selector: 'default_branch_dropdown' }})
+ .js-select-default-branch{ data: { default_branch: @project.default_branch, project_id: @project.id } }
.form-group
- help_text = _("When merge requests and commits in the default branch close, any issues they reference also close.")
diff --git a/doc/development/database/batched_background_migrations.md b/doc/development/database/batched_background_migrations.md
index 947e92bf83f..9730d767eed 100644
--- a/doc/development/database/batched_background_migrations.md
+++ b/doc/development/database/batched_background_migrations.md
@@ -545,7 +545,9 @@ To list the batched background migrations in the system, run this command:
This command supports the following options:
- Database selection:
- - `--database DATABASE_NAME`: Connects to the given database.
+ - `--database DATABASE_NAME`: Connects to the given database:
+ - `main`: Uses the main database (default).
+ - `ci`: Uses the CI database.
- Environment selection:
- `--dev`: Uses the `dev` environment.
- `--staging`: Uses the `staging` environment.
@@ -568,7 +570,9 @@ To see the status and progress of a specific batched background migration, run t
This command supports the following options:
- Database selection:
- - `--database DATABASE_NAME`: Connects to the given database.
+ - `--database DATABASE_NAME`: Connects to the given database:
+ - `main`: Uses the main database (default)
+ - `ci`: Uses the CI database
- Environment selection:
- `--dev`: Uses the `dev` environment.
- `--staging`: Uses the `staging` environment.
@@ -600,7 +604,9 @@ If you want to pause a batched background migration, you need to run the followi
This command supports the following options:
- Database selection:
- - `--database DATABASE_NAME`: Connects to the given database.
+ - `--database DATABASE_NAME`: Connects to the given database:
+ - `main`: Uses the main database (default).
+ - `ci`: Uses the CI database.
- Environment selection:
- `--dev`: Uses the `dev` environment.
- `--staging`: Uses the `staging` environment.
@@ -623,7 +629,9 @@ If you want to resume a batched background migration, you need to run the follow
This command supports the following options:
- Database selection:
- - `--database DATABASE_NAME`: Connects to the given database.
+ - `--database DATABASE_NAME`: Connects to the given database:
+ - `main`: Uses the main database (default).
+ - `ci`: Uses the CI database.
- Environment selection:
- `--dev`: Uses the `dev` environment.
- `--staging`: Uses the `staging` environment.
diff --git a/doc/user/application_security/terminology/index.md b/doc/user/application_security/terminology/index.md
index c5cc59805eb..2215c89aa4f 100644
--- a/doc/user/application_security/terminology/index.md
+++ b/doc/user/application_security/terminology/index.md
@@ -5,16 +5,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Secure and Protect terminology **(FREE)**
+# Secure and Govern terminology **(FREE)**
-This terminology list for GitLab Secure and Protect aims to:
+The glossary of terms aims to achieve the following:
-- Promote a ubiquitous language for discussing application security.
-- Improve the effectiveness of communication regarding GitLab application security features.
-- Get new contributors up to speed faster.
+- Promote a ubiquitous language that can be used everywhere - with customers, on issues, in Slack, in code.
+- Improve the effectiveness of communication between team members.
+- Reduce the potential for miscommunication.
+- Bring new team members and community contributors up to speed faster, reducing the time to productivity.
-This document defines application security terms in the specific context of GitLab Secure and
-Protect features. Terms may therefore have different meanings outside that context.
+The definitions of the terms outlined in this document are in the context of the GitLab
+products. Therefore, a term may have a different meaning to users outside of GitLab.
## Terms
@@ -28,9 +29,7 @@ an artifact after the job is complete. GitLab ingests this report, allowing user
manage found vulnerabilities. For more information, see [Security Scanner Integration](../../../development/integrations/secure.md).
Many GitLab analyzers follow a standard approach using Docker to run a wrapped scanner. For example,
-the Docker image `bandit-sast` is an analyzer that wraps the scanner `Bandit`. You can optionally
-use the [Common library](https://gitlab.com/gitlab-org/security-products/analyzers/common)
-to assist in building an Analyzer.
+the image `semgrep` is an analyzer that wraps the scanner `Semgrep`.
### Attack surface
@@ -44,6 +43,12 @@ The set of meaningful test cases that are generated while the fuzzer is running.
test case produces new coverage in the tested program. It's advised to re-use the corpus and pass it
to subsequent runs.
+### CNA
+
+[CVE](#cve) Numbering Authorities (CNAs) are organizations from around the world that are authorized by
+the [Mitre Corporation](https://cve.mitre.org/) to assign [CVE](#cve)s to vulnerabilities in products or
+services within their respective scope. [GitLab is a CNA](https://about.gitlab.com/security/cve/).
+
### CVE
Common Vulnerabilities and Exposures (CVE®) is a list of common identifiers for publicly known
@@ -63,6 +68,11 @@ architecture. If left unaddressed, weaknesses could result in systems, networks,
vulnerable to attack. The CWE List and associated classification taxonomy serve as a language that
you can use to identify and describe these weaknesses in terms of CWEs.
+### Deduplication
+
+When a category's process deems findings to be the same, or if they are similar enough that a noise reduction is
+required, only one finding is kept and the others are eliminated. Read more about the [deduplication process](../vulnerability_report/pipeline.md#deduplication-process).
+
### Duplicate finding
A legitimate finding that is reported multiple times. This can occur when different scanners
@@ -86,6 +96,13 @@ applications, and infrastructure.
Findings are all potential vulnerability items scanners identify in MRs/feature branches. Only after merging to default does a finding become a [vulnerability](#vulnerability).
+### Grouping
+
+A flexible and non-destructive way to visually organize vulnerabilities in groups when there are multiple findings
+that are likely related but do not qualify for deduplication. For example, you can include findings that should be
+evaluated together, would be fixed by the same action, or come from the same source. Grouping behavior for vulnerabilities is
+under development and tracked in issue [267588](https://gitlab.com/gitlab-org/gitlab/-/issues/267588).
+
### Insignificant finding
A legitimate finding that a particular customer doesn't care about.
@@ -93,16 +110,18 @@ A legitimate finding that a particular customer doesn't care about.
### Location fingerprint
A finding's location fingerprint is a text value that's unique for each location on the attack
-surface. Each Secure product defines this according to its type of attack surface. For example, SAST
+surface. Each security product defines this according to its type of attack surface. For example, SAST
incorporates file path and line number.
-### Package managers
+### Package managers and package types
+
+#### Package managers
-A Package manager is a system that manages your project dependencies.
+A package manager is a system that manages your project dependencies.
The package manager provides a method to install new dependencies (also referred to as "packages"), manage where packages are stored on your file system, and offer capabilities for you to publish your own packages.
-### Package types
+#### Package types
Each package manager, platform, type, or ecosystem has its own conventions and protocols to identify, locate, and provision software packages.
@@ -200,9 +219,26 @@ table.package-managers-and-types ul {
A page that displays findings discovered in the associated CI pipeline.
+### Post-filter
+
+Post-filters help reduce noise in the scanner results and automate manual tasks. You can specify criteria that updates
+or modifies vulnerability data based on scanner results. For example, you can flag findings as likely False Positives
+and automatically resolve vulnerabilities that are no longer detected. These are not permanent actions and can be changed.
+
+Support for automatically resolving findings is tracked in epic [7478](https://gitlab.com/groups/gitlab-org/-/epics/7478) and
+support for cheap scan is proposed in issue [349926](https://gitlab.com/gitlab-org/gitlab/-/issues/349926).
+
+### Pre-filter
+
+An irreversible action that is done to filter out target(s) before analysis occurs. This is usually provided to allow
+the user to reduce scope and noise as well as speed up the analysis. This should not be done if a record is needed as
+we currently do not store anything related to the skipped/excluded code or assets.
+
+Examples: `DS_EXCLUDED_PATHS` should `Exclude files and directories from the scan based on the paths provided.`
+
### Primary identifier
-A finding's primary identifier is a value unique to that finding. The external type and external ID
+A finding's primary identifier is a value that is unique to each finding. The external type and external ID
of the finding's [first identifier](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/v2.4.0-rc1/dist/sast-report-format.json#L228)
combine to create the value.
@@ -218,15 +254,19 @@ once it's imported into the database.
### Scan type (report type)
-The type of scan. This must be one of the following:
+Describes the type of scan. This must be one of the following:
+- `api_fuzzing`
- `cluster_image_scanning`
- `container_scanning`
+- `coverage_fuzzing`
- `dast`
- `dependency_scanning`
- `sast`
- `secret_detection`
+This list is subject to change as scanners are added.
+
### Scanner
Software that can scan for vulnerabilities. The resulting scan report is typically not in the
@@ -235,9 +275,12 @@ Software that can scan for vulnerabilities. The resulting scan report is typical
### Secure product
A group of features related to a specific area of application security with first-class support by
-GitLab. Products include Container Scanning, Dependency Scanning, Dynamic Application Security
-Testing (DAST), Secret Detection, Static Application Security Testing (SAST), and Fuzz Testing. Each
-of these products typically include one or more analyzers.
+GitLab.
+
+Products include Container Scanning, Dependency Scanning, Dynamic Application Security
+Testing (DAST), Secret Detection, Static Application Security Testing (SAST), and Fuzz Testing.
+
+Each of these products typically include one or more analyzers.
### Secure report format
@@ -267,6 +310,7 @@ is listed as GitLab.
A flaw that has a negative impact on the security of its environment. Vulnerabilities describe the
error or weakness, and don't describe where the error is located (see [finding](#finding)).
+
Each vulnerability maps to a unique finding.
Vulnerabilities exist in the default branch. Findings (see [finding](#finding)) are all potential vulnerability items scanners identify in MRs/feature branches. Only after merging to default does a finding become a vulnerability.
@@ -280,8 +324,9 @@ When a [report finding](#report-finding) is stored to the database, it becomes a
Deals with the responsibility of matching findings across scans so that a finding's life cycle can
be understood. Engineers and security teams use this information to decide whether to merge code
-changes, and to see unresolved findings and when they were introduced. Vulnerabilities are tracked
-by comparing the location fingerprint, primary identifier, and report type.
+changes, and to see unresolved findings and when they were introduced.
+
+Vulnerabilities are tracked by comparing the location fingerprint, primary identifier, and report type.
### Vulnerability occurrence
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index 46aac3ee119..aba971a1abb 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.38.0'
+ DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.38.1'
.dast-auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 54d2a8b6b7b..e59dc88aeb9 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.38.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.38.1'
.auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
index 9802b667851..bf48db90bb1 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.38.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.38.1'
.auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 39fc1672707..c6a314ff538 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -35291,6 +35291,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -36525,6 +36528,9 @@ msgstr ""
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
diff --git a/qa/qa/page/project/settings/default_branch.rb b/qa/qa/page/project/settings/default_branch.rb
index cc28b37b88f..575f9006c84 100644
--- a/qa/qa/page/project/settings/default_branch.rb
+++ b/qa/qa/page/project/settings/default_branch.rb
@@ -5,16 +5,22 @@ module QA
module Project
module Settings
class DefaultBranch < Page::Base
- include Page::Component::Select2
-
view 'app/views/projects/default_branch/_show.html.haml' do
element :save_changes_button
+ end
+
+ view 'app/assets/javascripts/projects/settings/components/default_branch_selector.vue' do
element :default_branch_dropdown
end
+ view 'app/assets/javascripts/ref/components/ref_selector.vue' do
+ element :ref_selector_searchbox
+ end
+
def set_default_branch(branch)
- find('.select2-chosen').click
- search_and_select(branch)
+ click_button :default_branch_dropdown
+ fill_in :ref_selector_searchbox, with: branch
+ click_button branch
end
def click_save_changes_button
diff --git a/spec/features/projects/settings/user_changes_default_branch_spec.rb b/spec/features/projects/settings/user_changes_default_branch_spec.rb
index 84e6c50cf61..508bbcc5327 100644
--- a/spec/features/projects/settings/user_changes_default_branch_spec.rb
+++ b/spec/features/projects/settings/user_changes_default_branch_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe 'Projects > Settings > User changes default branch' do
- include Select2Helper
-
let(:user) { create(:user) }
before do
@@ -17,16 +15,21 @@ RSpec.describe 'Projects > Settings > User changes default branch' do
let(:project) { create(:project, :repository, namespace: user.namespace) }
it 'allows to change the default branch', :js do
+ dropdown_selector = '[data-testid="default-branch-dropdown"]'
# Otherwise, running JS may overwrite our change to project_default_branch
wait_for_requests
- select2('fix', from: '#project_default_branch')
+ expect(page).to have_selector(dropdown_selector)
+ find(dropdown_selector).click
+
+ fill_in 'Search branch', with: 'fix'
+ click_button 'fix'
page.within '#default-branch-settings' do
click_button 'Save changes'
end
- expect(find('#project_default_branch', visible: false).value).to eq 'fix'
+ expect(find("#{dropdown_selector} input", visible: false).value).to eq 'fix'
end
end
@@ -34,7 +37,7 @@ RSpec.describe 'Projects > Settings > User changes default branch' do
let(:project) { create(:project_empty_repo, namespace: user.namespace) }
it 'does not show default branch selector' do
- expect(page).not_to have_selector('#project_default_branch')
+ expect(page).not_to have_selector('[data-testid="default-branch-dropdown"]')
end
end
end
diff --git a/spec/frontend/projects/settings/components/default_branch_selector_spec.js b/spec/frontend/projects/settings/components/default_branch_selector_spec.js
new file mode 100644
index 00000000000..94648d87524
--- /dev/null
+++ b/spec/frontend/projects/settings/components/default_branch_selector_spec.js
@@ -0,0 +1,46 @@
+import { shallowMount } from '@vue/test-utils';
+import DefaultBranchSelector from '~/projects/settings/components/default_branch_selector.vue';
+import RefSelector from '~/ref/components/ref_selector.vue';
+import { REF_TYPE_BRANCHES } from '~/ref/constants';
+
+describe('projects/settings/components/default_branch_selector', () => {
+ const persistedDefaultBranch = 'main';
+ const projectId = '123';
+ let wrapper;
+
+ const findRefSelector = () => wrapper.findComponent(RefSelector);
+
+ const buildWrapper = () => {
+ wrapper = shallowMount(DefaultBranchSelector, {
+ propsData: {
+ persistedDefaultBranch,
+ projectId,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('displays a RefSelector component', () => {
+ expect(findRefSelector().props()).toEqual({
+ value: persistedDefaultBranch,
+ enabledRefTypes: [REF_TYPE_BRANCHES],
+ projectId,
+ state: true,
+ translations: {
+ dropdownHeader: expect.any(String),
+ searchPlaceholder: expect.any(String),
+ },
+ useSymbolicRefNames: false,
+ name: 'project[default_branch]',
+ });
+
+ expect(findRefSelector().classes()).toContain('gl-w-full');
+ });
+});
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js
index 6c5af5a2625..96601a729b2 100644
--- a/spec/frontend/ref/components/ref_selector_spec.js
+++ b/spec/frontend/ref/components/ref_selector_spec.js
@@ -109,6 +109,8 @@ describe('Ref selector component', () => {
const findCommitDropdownItems = () => findCommitsSection().findAllComponents(GlDropdownItem);
const findFirstCommitDropdownItem = () => findCommitDropdownItems().at(0);
+ const findHiddenInputField = () => wrapper.find('[data-testid="selected-ref-form-field"]');
+
//
// Expecters
//
@@ -181,6 +183,24 @@ describe('Ref selector component', () => {
expect(findLoadingIcon().exists()).toBe(false);
});
});
+
+ describe('when name property is provided', () => {
+ it('renders an forrm input hidden field', () => {
+ const name = 'default_tag';
+
+ createComponent({ propsData: { name } });
+
+ expect(findHiddenInputField().attributes().name).toBe(name);
+ });
+ });
+
+ describe('when name property is not provided', () => {
+ it('renders an forrm input hidden field', () => {
+ createComponent();
+
+ expect(findHiddenInputField().exists()).toBe(false);
+ });
+ });
});
describe('post-initialization behavior', () => {
@@ -194,7 +214,7 @@ describe('Ref selector component', () => {
});
it('adds the provided ID to the GlDropdown instance', () => {
- expect(wrapper.attributes().id).toBe(id);
+ expect(wrapper.findComponent(GlDropdown).attributes().id).toBe(id);
});
});
@@ -202,7 +222,7 @@ describe('Ref selector component', () => {
const preselectedRef = fixtures.branches[0].name;
beforeEach(() => {
- createComponent({ propsData: { value: preselectedRef } });
+ createComponent({ propsData: { value: preselectedRef, name: 'selectedRef' } });
return waitForRequests();
});
@@ -210,6 +230,10 @@ describe('Ref selector component', () => {
it('renders the pre-selected ref name', () => {
expect(findButtonContent().text()).toBe(preselectedRef);
});
+
+ it('binds hidden input field to the pre-selected ref', () => {
+ expect(findHiddenInputField().attributes().value).toBe(preselectedRef);
+ });
});
describe('when the selected ref is updated by the parent component', () => {