diff --git a/CHANGELOG.md b/CHANGELOG.md index 79d8c52461a..ee8af966567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 13.11.4 (2021-05-14) + +### Fixed (3 changes) + +- Fix N+1 SQL queries in PipelinesController#show. !60794 +- Omit trailing slash when proxying pre-authorized routes with no suffix. !61638 +- Omit trailing slash when checking allowed requests in the read-only middleware. !61641 + + ## 13.11.3 (2021-04-30) ### Fixed (1 change) diff --git a/app/assets/javascripts/jobs/components/table/cells/job_cell.vue b/app/assets/javascripts/jobs/components/table/cells/job_cell.vue index 46108572a88..88a9f73258f 100644 --- a/app/assets/javascripts/jobs/components/table/cells/job_cell.vue +++ b/app/assets/javascripts/jobs/components/table/cells/job_cell.vue @@ -91,7 +91,9 @@ export default { data-testid="stuck-icon" /> -
master'
+ - fallback_branch_name = "#{Gitlab::DefaultBranch.value}"
%fieldset
.form-group
= f.label :default_branch_name, _('Default initial branch name'), class: 'label-light'
- = f.text_field :default_branch_name, placeholder: 'master', class: 'form-control gl-form-input'
+ = f.text_field :default_branch_name, placeholder: Gitlab::DefaultBranch.value, class: 'form-control gl-form-input'
%span.form-text.text-muted
= (_("Changes affect new repositories only. If not specified, Git's default name %{branch_name_default} will be used.") % { branch_name_default: fallback_branch_name } ).html_safe
diff --git a/app/views/groups/settings/repository/_initial_branch_name.html.haml b/app/views/groups/settings/repository/_initial_branch_name.html.haml
index efe690a0c2d..23ac7d51e4f 100644
--- a/app/views/groups/settings/repository/_initial_branch_name.html.haml
+++ b/app/views/groups/settings/repository/_initial_branch_name.html.haml
@@ -9,12 +9,12 @@
.settings-content
= form_for @group, url: group_path(@group, anchor: 'js-default-branch-name'), html: { class: 'fieldset-form' } do |f|
= form_errors(@group)
- - fallback_branch_name = 'master'
+ - fallback_branch_name = "#{Gitlab::DefaultBranch.value(object: @group)}"
%fieldset
.form-group
= f.label :default_branch_name, _('Default initial branch name'), class: 'label-light'
- = f.text_field :default_branch_name, value: group.namespace_settings&.default_branch_name, placeholder: 'master', class: 'form-control'
+ = f.text_field :default_branch_name, value: group.namespace_settings&.default_branch_name, placeholder: Gitlab::DefaultBranch.value(object: @group), class: 'form-control'
%span.form-text.text-muted
= (_("Changes affect new repositories only. If not specified, either the configured application-wide default or Git's default name %{branch_name_default} will be used.") % { branch_name_default: fallback_branch_name }).html_safe
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index ceb312450be..bc0d14743b9 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -3,22 +3,24 @@
- `assets/javascripts/diffs/components/commit_item.vue`
EXCEPTION WARNING - see above `.vue` file for de-sync drift
+
+ WARNING: When introducing new content here, please consider what
+ changes may need to be made in the cache keys used to
+ wrap this view, found in
+ CommitsHelper#commit_partial_cache_key
-#-----------------------------------------------------------------
-- view_details = local_assigns.fetch(:view_details, false)
-- merge_request = local_assigns.fetch(:merge_request, nil)
-- project = local_assigns.fetch(:project) { merge_request&.project }
-- ref = local_assigns.fetch(:ref) { merge_request&.source_branch }
-- commit = commit.present(current_user: current_user)
-- commit_status = commit.status_for(ref)
-- collapsible = local_assigns.fetch(:collapsible, true)
-- link_data_attrs = local_assigns.fetch(:link_data_attrs, {})
-
-- link = commit_path(project, commit, merge_request: merge_request)
-
+- view_details = local_assigns.fetch(:view_details, false)
+- merge_request = local_assigns.fetch(:merge_request, nil)
+- project = local_assigns.fetch(:project) { merge_request&.project }
+- ref = local_assigns.fetch(:ref) { merge_request&.source_branch }
+- commit = commit.present(current_user: current_user)
+- commit_status = commit.status_for(ref)
+- collapsible = local_assigns.fetch(:collapsible, true)
+- link_data_attrs = local_assigns.fetch(:link_data_attrs, {})
+- link = commit_path(project, commit, merge_request: merge_request)
- show_project_name = local_assigns.fetch(:show_project_name, false)
%li{ class: ["commit flex-row", ("js-toggle-container" if collapsible)], id: "commit-#{commit.short_id}" }
-
.avatar-cell.d-none.d-sm-block
= author_avatar(commit, size: 40, has_tooltip: false)
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index 9e2dca3ad71..e6c9a7166a9 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -3,8 +3,8 @@
- ref = local_assigns.fetch(:ref) { merge_request&.source_branch }
- can_update_merge_request = can?(current_user, :update_merge_request, @merge_request)
-- commits = @commits
-- context_commits = @context_commits
+- commits = @commits&.map { |commit| commit.present(current_user: current_user) }
+- context_commits = @context_commits&.map { |commit| commit.present(current_user: current_user) }
- hidden = @hidden_commit_count
- commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, daily_commits|
@@ -14,7 +14,10 @@
%li.commits-row{ data: { day: day } }
%ul.content-list.commit-list.flex-list
- = render partial: 'projects/commits/commit', collection: daily_commits, locals: { project: project, ref: ref, merge_request: merge_request }
+ - if Feature.enabled?(:cached_commits, project, default_enabled: :yaml)
+ = render partial: 'projects/commits/commit', collection: daily_commits, locals: { project: project, ref: ref, merge_request: merge_request }, cached: -> (commit) { commit_partial_cache_key(commit, ref: ref, merge_request: merge_request, request: request) }
+ - else
+ = render partial: 'projects/commits/commit', collection: daily_commits, locals: { project: project, ref: ref, merge_request: merge_request }
- if context_commits.present?
%li.commit-header.js-commit-header
@@ -25,7 +28,10 @@
%li.commits-row
%ul.content-list.commit-list.flex-list
- = render partial: 'projects/commits/commit', collection: context_commits, locals: { project: project, ref: ref, merge_request: merge_request }
+ - if Feature.enabled?(:cached_commits, project, default_enabled: :yaml)
+ = render partial: 'projects/commits/commit', collection: context_commits, locals: { project: project, ref: ref, merge_request: merge_request }, cached: -> (commit) { commit_partial_cache_key(commit, ref: ref, merge_request: merge_request, request: request) }
+ - else
+ = render partial: 'projects/commits/commit', collection: context_commits, locals: { project: project, ref: ref, merge_request: merge_request }
- if hidden > 0
%li.gl-alert.gl-alert-warning
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index e3ab184ec6f..426d022da26 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -4,11 +4,11 @@
%h3.page-title
= _("Compare Git revisions")
.sub-header-block
- - example_master = capture do
- %code.ref-name master
+ - example_branch = capture do
+ %code.ref-name= @project.default_branch_or_main
- example_sha = capture do
%code.ref-name 4eedf23
- = html_escape(_("Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request.")) % { master: example_master.html_safe, sha: example_sha.html_safe }
+ = html_escape(_("Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request.")) % { branch: example_branch.html_safe, sha: example_sha.html_safe }
%br
= html_escape(_("Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision.")) % { b_open: ''.html_safe, b_close: ''.html_safe }
diff --git a/changelogs/unreleased/330787-omits-trailing-slash-when-checking-for-allowed-requests.yml b/changelogs/unreleased/330787-omits-trailing-slash-when-checking-for-allowed-requests.yml
deleted file mode 100644
index 6e04471fa13..00000000000
--- a/changelogs/unreleased/330787-omits-trailing-slash-when-checking-for-allowed-requests.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Omit trailing slash when checking allowed requests in the read-only middleware
-merge_request: 61641
-author:
-type: fixed
diff --git a/changelogs/unreleased/id-rename-main-to-master-in-views.yml b/changelogs/unreleased/id-rename-main-to-master-in-views.yml
new file mode 100644
index 00000000000..7e3f45274f1
--- /dev/null
+++ b/changelogs/unreleased/id-rename-main-to-master-in-views.yml
@@ -0,0 +1,5 @@
+---
+title: Rename master to main in views placeholders
+merge_request: 61252
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-avoid-trailing-slash-in-proxy.yml b/changelogs/unreleased/sh-avoid-trailing-slash-in-proxy.yml
deleted file mode 100644
index 3bea1874ff3..00000000000
--- a/changelogs/unreleased/sh-avoid-trailing-slash-in-proxy.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Omit trailing slash when proxying pre-authorized routes with no suffix
-merge_request: 61638
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-nplus-one-pipelines-show.yml b/changelogs/unreleased/sh-fix-nplus-one-pipelines-show.yml
deleted file mode 100644
index ebaf2aee123..00000000000
--- a/changelogs/unreleased/sh-fix-nplus-one-pipelines-show.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix N+1 SQL queries in PipelinesController#show
-merge_request: 60794
-author:
-type: fixed
diff --git a/config/feature_flags/development/cached_commits.yml b/config/feature_flags/development/cached_commits.yml
new file mode 100644
index 00000000000..0758f8a3f53
--- /dev/null
+++ b/config/feature_flags/development/cached_commits.yml
@@ -0,0 +1,8 @@
+---
+name: cached_commits
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61617
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330968
+milestone: '13.12'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/helpers/vendor_dll_hash.js b/config/helpers/vendor_dll_hash.js
index cdbaebc9789..9b99b4c4ae9 100644
--- a/config/helpers/vendor_dll_hash.js
+++ b/config/helpers/vendor_dll_hash.js
@@ -1,5 +1,5 @@
-const fs = require('fs');
const crypto = require('crypto');
+const fs = require('fs');
const path = require('path');
const CACHE_PATHS = [
diff --git a/config/karma.config.js b/config/karma.config.js
index 1c2dd21c189..3e125759357 100644
--- a/config/karma.config.js
+++ b/config/karma.config.js
@@ -1,8 +1,8 @@
/* eslint-disable no-inner-declarations, no-param-reassign */
+const path = require('path');
const chalk = require('chalk');
const argumentsParser = require('commander');
const glob = require('glob');
-const path = require('path');
const webpack = require('webpack');
const IS_EE = require('./helpers/is_ee_env');
const webpackConfig = require('./webpack.config.js');
diff --git a/config/webpack.config.js b/config/webpack.config.js
index d48b22f8024..d40d14e1158 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -1,11 +1,11 @@
const fs = require('fs');
+const path = require('path');
const SOURCEGRAPH_VERSION = require('@sourcegraph/code-host-integration/package.json').version;
const CompressionPlugin = require('compression-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const glob = require('glob');
-const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const VUE_LOADER_VERSION = require('vue-loader/package.json').version;
const VUE_VERSION = require('vue/package.json').version;
diff --git a/doc/ci/jobs/job_control.md b/doc/ci/jobs/job_control.md
index 14555a05672..6e9197c223b 100644
--- a/doc/ci/jobs/job_control.md
+++ b/doc/ci/jobs/job_control.md
@@ -63,7 +63,7 @@ except `main` and branches that start with `release/`.
### `only: variables` / `except: variables` examples
-You can use `except:variables` to exclude jobs based on a commit message:
+You can use [`except:variables`](../yaml/README.md#onlyvariables--exceptvariables) to exclude jobs based on a commit message:
```yaml
end-to-end:
@@ -223,6 +223,48 @@ test:
- "README.md"
```
+## Use predefined CI/CD variables to run jobs only in specific pipeline types
+
+You can use [predefined CI/CD variables](../variables/predefined_variables.md) to choose
+which pipeline types jobs run in, with:
+
+- [`rules`](../yaml/README.md#rules)
+- [`only:variables`](../yaml/README.md#onlyvariables--exceptvariables)
+- [`except:variables`](../yaml/README.md#onlyvariables--exceptvariables)
+
+The following table lists some of the variables that you can use, and the pipeline
+types the variables can control for:
+
+- Branch pipelines that run for Git `push` events to a branch, like new commits or tags.
+- Tag pipelines that run only when a new Git tag is pushed to a branch.
+- [Merge request pipelines](../merge_request_pipelines/index.md) that run for changes
+ to a merge request, like new commits or selecting the **Run pipeline** button
+ in a merge request's pipelines tab.
+- [Scheduled pipelines](../pipelines/schedules.md).
+
+| Variables | Branch | Tag | Merge request | Scheduled |
+|--------------------------------------------|--------|-----|---------------|-----------|
+| `CI_COMMIT_BRANCH` | Yes | | | Yes |
+| `CI_COMMIT_TAG` | | Yes | | Yes, if the scheduled pipeline is configured to run on a tag. |
+| `CI_PIPELINE_SOURCE = push` | Yes | Yes | | |
+| `CI_PIPELINE_SOURCE = scheduled` | | | | Yes |
+| `CI_PIPELINE_SOURCE = merge_request_event` | | | Yes | |
+| `CI_MERGE_REQUEST_IID` | | | Yes | |
+
+For example, to configure a job to run for merge request pipelines and scheduled pipelines,
+but not branch or tag pipelines:
+
+```yaml
+job1:
+ script:
+ - echo
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ - if: $CI_PIPELINE_SOURCE == "scheduled"
+ - if: $CI_PIPELINE_SOURCE == "push"
+ when: never
+```
+
## Regular expressions
The `@` symbol denotes the beginning of a ref's repository path.
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 4b30d08ff10..1f323a311e1 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -36,14 +36,14 @@ The keywords available for jobs are:
| [`coverage`](#coverage) | Code coverage settings for a given job. |
| [`dependencies`](#dependencies) | Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from. |
| [`environment`](#environment) | Name of an environment to which the job deploys. |
-| [`except`](#only--except) | Control when jobs are not created. |
+| [`except`](#only--except) | Control when jobs are not created. |
| [`extends`](#extends) | Configuration entries that this job inherits from. |
| [`image`](#image) | Use Docker images. |
| [`include`](#include) | Include external YAML files. |
| [`inherit`](#inherit) | Select which global defaults all jobs inherit. |
| [`interruptible`](#interruptible) | Defines if a job can be canceled when made redundant by a newer run. |
| [`needs`](#needs) | Execute jobs earlier than the stage ordering. |
-| [`only`](#only--except) | Control when jobs are created. |
+| [`only`](#only--except) | Control when jobs are created. |
| [`pages`](#pages) | Upload the result of a job to use with GitLab Pages. |
| [`parallel`](#parallel) | How many instances of a job should be run in parallel. |
| [`release`](#release) | Instructs the runner to generate a [release](../../user/project/releases/index.md) object. |
@@ -1615,7 +1615,7 @@ Four keywords can be used with `only` and `except`:
- [`changes`](#onlychanges--exceptchanges)
- [`kubernetes`](#onlykubernetes--exceptkubernetes)
-See [control jobs with `only` and `except`](../jobs/job_control.md#specify-when-jobs-run-with-only-and-except)
+See [specify when jobs run with `only` and `except`](../jobs/job_control.md#specify-when-jobs-run-with-only-and-except)
for more details and examples.
#### `only:refs` / `except:refs`
@@ -3632,10 +3632,10 @@ failure.
`artifacts:when` can be set to one of the following values:
1. `on_success` (default): Upload artifacts only when the job succeeds.
-1. `on_failure`: Upload artifacts only when the job fails. Useful, for example, when
+1. `on_failure`: Upload artifacts only when the job fails.
+1. `always`: Always upload artifacts. Useful, for example, when
[uploading artifacts](../unit_test_reports.md#viewing-junit-screenshots-on-gitlab) required to
troubleshoot failing tests.
-1. `always`: Always upload artifacts.
For example, to upload artifacts only when a job fails:
diff --git a/doc/development/stage_group_dashboards.md b/doc/development/stage_group_dashboards.md
index 58e998e46a8..d6d607df2dd 100644
--- a/doc/development/stage_group_dashboards.md
+++ b/doc/development/stage_group_dashboards.md
@@ -57,7 +57,7 @@ component has 2 indicators:
The calculation to a ratio then happens as follows:
```math
-\frac {operations\_meeting\_apdex + (total\_operations - operations\_with_\errors)} {total\_apdex\_measurements + total\_operations}
+\frac {operations\_meeting\_apdex + (total\_operations - operations\_with\_errors)} {total\_apdex\_measurements + total\_operations}
```
*Caveat:* Not all components are included, causing the
diff --git a/doc/development/usage_ping/index.md b/doc/development/usage_ping/index.md
index e79cd127d5a..292e1256cb8 100644
--- a/doc/development/usage_ping/index.md
+++ b/doc/development/usage_ping/index.md
@@ -266,7 +266,7 @@ To remove a deprecated metric:
[fixtures](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/spec/support/usage_data_helpers.rb#L540)
used to test
[`UsageDataController#create`](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/3760ef28/spec/controllers/usage_data_controller_spec.rb#L75)
- endpoint, and assure that test suite does not fail when metric that you wish to remove is not included into test payload.
+ endpoint, and assure that test suite does not fail when metric that you wish to remove is not included into test payload.
1. Create an issue in the
[GitLab Data Team project](https://gitlab.com/gitlab-data/analytics/-/issues).
@@ -276,7 +276,7 @@ To remove a deprecated metric:
This step can be skipped if verification done during [deprecation process](#3-deprecate-a-metric)
reported that metric is not required by any data transformation in Snowflake data warehouse nor it is
used by any of SiSense dashboards.
-
+
1. After you verify the metric can be safely removed,
update the attributes of the metric's YAML definition:
@@ -1024,7 +1024,13 @@ On GitLab.com, we have DangerBot setup to monitor Product Intelligence related f
### 10. Verify your metric
-On GitLab.com, the Product Intelligence team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "SaaS" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric.
+On GitLab.com, the Product Intelligence team regularly [monitors Usage Ping](https://gitlab.com/groups/gitlab-org/-/epics/6000).
+They may alert you that your metrics need further optimization to run quicker and with greater success.
+
+The Usage Ping JSON payload for GitLab.com is shared in the
+[#g_product_intelligence](https://gitlab.slack.com/archives/CL3A7GFPF) Slack channel every week.
+
+You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "SaaS" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric.
### Usage Ping local setup
diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..5216a46745c
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml
@@ -0,0 +1,77 @@
+# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html
+
+browser_performance:
+ stage: performance
+ image: docker:19.03.12
+ allow_failure: true
+ variables:
+ DOCKER_TLS_CERTDIR: ""
+ SITESPEED_IMAGE: sitespeedio/sitespeed.io
+ SITESPEED_VERSION: 14.1.0
+ SITESPEED_OPTIONS: ''
+ services:
+ - docker:19.03.12-dind
+ script:
+ - |
+ if ! docker info &>/dev/null; then
+ if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
+ export DOCKER_HOST='tcp://localhost:2375'
+ fi
+ fi
+ - export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
+ - mkdir gitlab-exporter
+ # Busybox wget does not support proxied HTTPS, get the real thing.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/287611.
+ - (env | grep -i _proxy= 2>&1 >/dev/null) && apk --no-cache add wget
+ - wget -O gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.1.0/index.js
+ - mkdir sitespeed-results
+ - |
+ function propagate_env_vars() {
+ CURRENT_ENV=$(printenv)
+
+ for VAR_NAME; do
+ echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
+ done
+ }
+ - |
+ if [ -f .gitlab-urls.txt ]
+ then
+ sed -i -e 's@^@'"$CI_ENVIRONMENT_URL"'@' .gitlab-urls.txt
+ docker run \
+ $(propagate_env_vars \
+ auto_proxy \
+ https_proxy \
+ http_proxy \
+ no_proxy \
+ AUTO_PROXY \
+ HTTPS_PROXY \
+ HTTP_PROXY \
+ NO_PROXY \
+ ) \
+ --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results .gitlab-urls.txt $SITESPEED_OPTIONS
+ else
+ docker run \
+ $(propagate_env_vars \
+ auto_proxy \
+ https_proxy \
+ http_proxy \
+ no_proxy \
+ AUTO_PROXY \
+ HTTPS_PROXY \
+ HTTP_PROXY \
+ NO_PROXY \
+ ) \
+ --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL" $SITESPEED_OPTIONS
+ fi
+ - mv sitespeed-results/data/performance.json browser-performance.json
+ artifacts:
+ paths:
+ - sitespeed-results/
+ reports:
+ browser_performance: browser-performance.json
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$PERFORMANCE_DISABLED'
+ when: never
+ - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
diff --git a/lib/gitlab/default_branch.rb b/lib/gitlab/default_branch.rb
index 73c9ac07753..6bd9a5675c4 100644
--- a/lib/gitlab/default_branch.rb
+++ b/lib/gitlab/default_branch.rb
@@ -3,8 +3,8 @@
# Class is used while we're migrating from master to main
module Gitlab
module DefaultBranch
- def self.value(project: nil)
- Feature.enabled?(:main_branch_over_master, project, default_enabled: :yaml) ? 'main' : 'master'
+ def self.value(object: nil)
+ Feature.enabled?(:main_branch_over_master, object, default_enabled: :yaml) ? 'main' : 'master'
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8087d3c3c32..01a5e40941a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6334,7 +6334,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -17894,7 +17894,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
diff --git a/package.json b/package.json
index 57d229cd8e9..173f618e5e9 100644
--- a/package.json
+++ b/package.json
@@ -186,7 +186,7 @@
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@gitlab/eslint-plugin": "8.3.0",
+ "@gitlab/eslint-plugin": "8.4.0",
"@gitlab/stylelint-config": "2.3.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "1.1.2",
@@ -201,7 +201,7 @@
"docdash": "^1.0.2",
"eslint": "7.26.0",
"eslint-import-resolver-jest": "3.0.0",
- "eslint-import-resolver-webpack": "0.13.0",
+ "eslint-import-resolver-webpack": "0.13.1",
"eslint-plugin-jasmine": "4.1.2",
"eslint-plugin-no-jquery": "2.6.0",
"gettext-extractor": "^3.5.3",
diff --git a/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js b/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
index 22a4aac762b..4c439caa1da 100755
--- a/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
+++ b/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
@@ -8,8 +8,8 @@ if (process.env.RAILS_ENV !== 'production') {
}
const fs = require('fs');
-const glob = require('glob');
const path = require('path');
+const glob = require('glob');
const pjs = require('postcss');
const paths = glob.sync('public/assets/page_bundles/_mixins_and_variables_and_functions*.css', {
diff --git a/scripts/frontend/merge_coverage_frontend.js b/scripts/frontend/merge_coverage_frontend.js
index 6b3826ddac7..bd56b0d5868 100644
--- a/scripts/frontend/merge_coverage_frontend.js
+++ b/scripts/frontend/merge_coverage_frontend.js
@@ -1,8 +1,8 @@
+const { resolve } = require('path');
const { sync } = require('glob');
const { createCoverageMap } = require('istanbul-lib-coverage');
const { createContext } = require('istanbul-lib-report');
const { create } = require('istanbul-reports');
-const { resolve } = require('path');
const coverageMap = createCoverageMap();
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
index 9e96c154546..b2ed79cd75a 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
@@ -1,3 +1,6 @@
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+
+import AccessorUtilities from '~/lib/utils/accessor';
import {
stripQuotes,
uniqueTokens,
@@ -5,6 +8,8 @@ import {
processFilters,
filterToQueryObject,
urlQueryToFilter,
+ getRecentlyUsedTokenValues,
+ setTokenValueToRecentlyUsed,
} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
import {
@@ -14,6 +19,12 @@ import {
tokenValuePlain,
} from './mock_data';
+const mockStorageKey = 'recent-tokens';
+
+function setLocalStorageAvailability(isAvailable) {
+ jest.spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').mockReturnValue(isAvailable);
+}
+
describe('Filtered Search Utils', () => {
describe('stripQuotes', () => {
it.each`
@@ -249,3 +260,79 @@ describe('urlQueryToFilter', () => {
expect(res).toEqual(result);
});
});
+
+describe('getRecentlyUsedTokenValues', () => {
+ useLocalStorageSpy();
+
+ beforeEach(() => {
+ localStorage.removeItem(mockStorageKey);
+ });
+
+ it('returns array containing recently used token values from provided recentTokenValuesStorageKey', () => {
+ setLocalStorageAvailability(true);
+
+ const mockExpectedArray = [{ foo: 'bar' }];
+ localStorage.setItem(mockStorageKey, JSON.stringify(mockExpectedArray));
+
+ expect(getRecentlyUsedTokenValues(mockStorageKey)).toEqual(mockExpectedArray);
+ });
+
+ it('returns empty array when provided recentTokenValuesStorageKey does not have anything in localStorage', () => {
+ setLocalStorageAvailability(true);
+
+ expect(getRecentlyUsedTokenValues(mockStorageKey)).toEqual([]);
+ });
+
+ it('returns empty array when when access to localStorage is not available', () => {
+ setLocalStorageAvailability(false);
+
+ expect(getRecentlyUsedTokenValues(mockStorageKey)).toEqual([]);
+ });
+});
+
+describe('setTokenValueToRecentlyUsed', () => {
+ const mockTokenValue1 = { foo: 'bar' };
+ const mockTokenValue2 = { bar: 'baz' };
+ useLocalStorageSpy();
+
+ beforeEach(() => {
+ localStorage.removeItem(mockStorageKey);
+ });
+
+ it('adds provided tokenValue to localStorage for recentTokenValuesStorageKey', () => {
+ setLocalStorageAvailability(true);
+
+ setTokenValueToRecentlyUsed(mockStorageKey, mockTokenValue1);
+
+ expect(JSON.parse(localStorage.getItem(mockStorageKey))).toEqual([mockTokenValue1]);
+ });
+
+ it('adds provided tokenValue to localStorage at the top of existing values (i.e. Stack order)', () => {
+ setLocalStorageAvailability(true);
+
+ setTokenValueToRecentlyUsed(mockStorageKey, mockTokenValue1);
+ setTokenValueToRecentlyUsed(mockStorageKey, mockTokenValue2);
+
+ expect(JSON.parse(localStorage.getItem(mockStorageKey))).toEqual([
+ mockTokenValue2,
+ mockTokenValue1,
+ ]);
+ });
+
+ it('ensures that provided tokenValue is not added twice', () => {
+ setLocalStorageAvailability(true);
+
+ setTokenValueToRecentlyUsed(mockStorageKey, mockTokenValue1);
+ setTokenValueToRecentlyUsed(mockStorageKey, mockTokenValue1);
+
+ expect(JSON.parse(localStorage.getItem(mockStorageKey))).toEqual([mockTokenValue1]);
+ });
+
+ it('does not add any value when acess to localStorage is not available', () => {
+ setLocalStorageAvailability(false);
+
+ setTokenValueToRecentlyUsed(mockStorageKey, mockTokenValue1);
+
+ expect(JSON.parse(localStorage.getItem(mockStorageKey))).toBeNull();
+ });
+});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
new file mode 100644
index 00000000000..0db47f1f189
--- /dev/null
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
@@ -0,0 +1,228 @@
+import { GlFilteredSearchToken } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import {
+ mockRegularLabel,
+ mockLabels,
+} from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
+
+import { DEFAULT_LABELS } from '~/vue_shared/components/filtered_search_bar/constants';
+import {
+ getRecentlyUsedTokenValues,
+ setTokenValueToRecentlyUsed,
+} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
+import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
+
+import { mockLabelToken } from '../mock_data';
+
+jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils');
+
+const mockStorageKey = 'recent-tokens-label_name';
+
+const defaultStubs = {
+ Portal: true,
+ GlFilteredSearchToken: {
+ template: `
+