提交 2abb1b54 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 8320f795
import axios from 'axios';
import csrf from './csrf';
import suppressAjaxErrorsDuringNavigation from './suppress_ajax_errors_during_navigation';
axios.defaults.headers.common[csrf.headerKey] = csrf.token;
// Used by Rails to check if it is a valid XHR request
......@@ -25,6 +26,20 @@ axios.interceptors.response.use(
},
);
let isUserNavigating = false;
window.addEventListener('beforeunload', () => {
isUserNavigating = true;
});
// Ignore AJAX errors caused by requests
// being cancelled due to browser navigation
const { gon } = window;
const featureFlagEnabled = gon && gon.features && gon.features.suppressAjaxNavigationErrors;
axios.interceptors.response.use(
response => response,
err => suppressAjaxErrorsDuringNavigation(err, isUserNavigating, featureFlagEnabled),
);
export default axios;
/**
......
......@@ -15,6 +15,8 @@ export const getPagePath = (index = 0) => {
return page.split(':')[index];
};
export const getDashPath = (path = window.location.pathname) => path.split('/-/')[1] || null;
export const isInGroupsPage = () => getPagePath() === 'groups';
export const isInProjectPage = () => getPagePath() === 'projects';
......
/**
* An Axios error interceptor that suppresses AJAX errors caused
* by the request being cancelled when the user navigates to a new page
*/
export default (err, isUserNavigating, featureFlagEnabled) => {
if (featureFlagEnabled && isUserNavigating && err.code === 'ECONNABORTED') {
// If the user is navigating away from the current page,
// prevent .then() and .catch() handlers from being
// called by returning a Promise that never resolves
return new Promise(() => {});
}
// The error is not related to browser navigation,
// so propagate the error
return Promise.reject(err);
};
......@@ -69,6 +69,7 @@ export default {
'commentsDisabled',
'getNoteableData',
'userCanReply',
'discussionTabCounter',
]),
noteableType() {
return this.noteableData.noteableType;
......@@ -95,13 +96,13 @@ export default {
}
},
allDiscussions() {
if (this.discussonsCount) {
this.discussonsCount.textContent = this.allDiscussions.length;
if (this.discussionsCount && !this.isLoading) {
this.discussionsCount.textContent = this.discussionTabCounter;
}
},
},
created() {
this.discussonsCount = document.querySelector('.js-discussions-count');
this.discussionsCount = document.querySelector('.js-discussions-count');
this.setNotesData(this.notesData);
this.setNoteableData(this.noteableData);
......
/* eslint-disable no-new */
import { getPagePath } from '~/lib/utils/common_utils';
import { getPagePath, getDashPath } from '~/lib/utils/common_utils';
import { ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED } from '~/groups/constants';
import NewGroupChild from '~/groups/new_group_child';
import notificationsDropdown from '~/notifications_dropdown';
......@@ -12,9 +12,8 @@ import GroupTabs from './group_tabs';
export default function initGroupDetails(actionName = 'show') {
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
const loadableActions = [ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED];
const paths = window.location.pathname.split('/');
const subpath = paths[paths.length - 1];
let action = loadableActions.includes(subpath) ? subpath : getPagePath(1);
const dashPath = getDashPath();
let action = loadableActions.includes(dashPath) ? dashPath : getPagePath(1);
if (actionName && action === actionName) {
action = 'show'; // 'show' resets GroupTabs to default action through base class
}
......
......@@ -11,6 +11,8 @@ module Boards
def index
lists = Boards::Lists::ListService.new(board.parent, current_user).execute(board)
List.preload_preferences_for_user(lists, current_user)
render json: serialize_as_json(lists)
end
......@@ -51,7 +53,10 @@ module Boards
service = Boards::Lists::GenerateService.new(board_parent, current_user)
if service.execute(board)
lists = board.lists.movable.preload_associations(current_user)
lists = board.lists.movable.preload_associations
List.preload_preferences_for_user(lists, current_user)
render json: serialize_as_json(lists)
else
head :unprocessable_entity
......
......@@ -234,6 +234,7 @@ module Ci
end
after_transition pending: :running do |build|
build.pipeline.persistent_ref.create
build.deployment&.run
build.run_after_commit do
......
# frozen_string_literal: true
module Ci
##
# The persistent pipeline ref to ensure runners can safely fetch source code
# even if force-push/source-branch-deletion happens.
class PersistentRef
include ActiveModel::Model
attr_accessor :pipeline
delegate :project, :sha, to: :pipeline
delegate :repository, to: :project
delegate :ref_exists?, :create_ref, :delete_refs, to: :repository
def exist?
return unless enabled?
ref_exists?(path)
rescue
false
end
def create
return unless enabled? && !exist?
create_ref(sha, path)
rescue => e
Gitlab::Sentry
.track_acceptable_exception(e, extra: { pipeline_id: pipeline.id })
end
def delete
return unless enabled?
delete_refs(path)
rescue Gitlab::Git::Repository::NoRepository
# no-op
rescue => e
Gitlab::Sentry
.track_acceptable_exception(e, extra: { pipeline_id: pipeline.id })
end
def path
"refs/#{Repository::REF_PIPELINES}/#{pipeline.id}"
end
private
def enabled?
Feature.enabled?(:depend_on_persistent_pipeline_ref, project)
end
end
end
......@@ -174,6 +174,8 @@ module Ci
after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
pipeline.run_after_commit do
pipeline.persistent_ref.delete
pipeline.all_merge_requests.each do |merge_request|
next unless merge_request.auto_merge_enabled?
......@@ -853,6 +855,10 @@ module Ci
end
end
def persistent_ref
@persistent_ref ||= PersistentRef.new(pipeline: self)
end
private
def ci_yaml_from_repo
......
......@@ -21,20 +21,10 @@ class List < ApplicationRecord
scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
scope :preload_associations, -> (user) do
preload(:board, label: :priorities)
end
scope :preload_associations, -> { preload(:board, label: :priorities) }
scope :ordered, -> { order(:list_type, :position) }
# Loads list with preferences for given user
# if preferences exists for user or not
scope :with_preferences_for, -> (user) do
return unless user
includes(:list_user_preferences).where(list_user_preferences: { user_id: [user.id, nil] })
end
alias_method :preferences, :list_user_preferences
class << self
......@@ -45,25 +35,25 @@ class List < ApplicationRecord
def movable_types
[:label]
end
def preload_preferences_for_user(lists, user)
return unless user
lists.each { |list| list.preferences_for(user) }
end
end
def preferences_for(user)
return preferences.build unless user
if preferences.loaded?
preloaded_preferences_for(user)
else
preferences.find_or_initialize_by(user: user)
end
end
BatchLoader.for(list_id: id, user_id: user.id).batch(default_value: preferences.build(user: user)) do |items, loader|
list_ids = items.map { |i| i[:list_id] }
user_ids = items.map { |i| i[:user_id] }
def preloaded_preferences_for(user)
user_preferences =
preferences.find do |preference|
preference.user_id == user.id
ListUserPreference.where(list_id: list_ids, user_id: user_ids).find_each do |preference|
loader.call({ list_id: preference.list_id, user_id: preference.user_id }, preference)
end
user_preferences || preferences.build(user: user)
end
end
def update_preferences_for(user, preferences = {})
......
......@@ -6,6 +6,7 @@ class Repository
REF_MERGE_REQUEST = 'merge-requests'
REF_KEEP_AROUND = 'keep-around'
REF_ENVIRONMENTS = 'environments'
REF_PIPELINES = 'pipelines'
ARCHIVE_CACHE_TIME = 60 # Cache archives referred to by a (mutable) ref for 1 minute
ARCHIVE_CACHE_TIME_IMMUTABLE = 3600 # Cache archives referred to by an immutable reference for 1 hour
......@@ -16,7 +17,7 @@ class Repository
replace
#{REF_ENVIRONMENTS}
#{REF_KEEP_AROUND}
#{REF_ENVIRONMENTS}
#{REF_PIPELINES}
].freeze
include Gitlab::RepositoryCacheAdapter
......
......@@ -34,7 +34,8 @@ module Ci
def refspecs
specs = []
specs << refspec_for_merge_request_ref if merge_request_ref?
specs << refspec_for_pipeline_ref if merge_request_ref?
specs << refspec_for_persistent_ref if persistent_ref_exist?
if git_depth > 0
specs << refspec_for_branch(ref) if branch? || legacy_detached_merge_request_pipeline?
......@@ -86,10 +87,22 @@ module Ci
"+#{Gitlab::Git::TAG_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_TAG_PREFIX}#{ref}"
end
def refspec_for_merge_request_ref
def refspec_for_pipeline_ref
"+#{ref}:#{ref}"
end
def refspec_for_persistent_ref
"+#{persistent_ref_path}:#{persistent_ref_path}"
end
def persistent_ref_exist?
pipeline.persistent_ref.exist?
end
def persistent_ref_path
pipeline.persistent_ref.path
end
def git_depth_variable
strong_memoize(:git_depth_variable) do
variables&.find { |variable| variable[:key] == 'GIT_DEPTH' }
......
......@@ -6,7 +6,7 @@ module Boards
def execute(board)
board.lists.create(list_type: :backlog) unless board.lists.backlog.exists?
board.lists.preload_associations(current_user)
board.lists.preload_associations
end
end
end
......
---
title: Naming a project "shared" will no longer automatically open the "Shared Projects" tab.
merge_request: 16847
author: Jesse Hall @jessehall3
type: fixed
---
title: Create a persistent ref per pipeline for keeping pipelines run from force-push
and merged results
merge_request: 17043
author:
type: fixed
---
title: Add trigram index on snippet content
merge_request: 17806
author:
type: performance
---
title: Increase the limit of includes in CI file to 100
merge_request: 17807
author:
type: fixed
---
title: Suppress error messages shown when navigating to a new page
merge_request: 17706
author:
type: fixed
......@@ -209,9 +209,7 @@ module.exports = {
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local].[hash:8].[ext]',
},
name: '[name].[hash:8].[ext]',
},
},
],
......
# frozen_string_literal: true
class AddIndexOnSnippetContent < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'index_snippets_on_content_trigram'
disable_ddl_transaction!
def up
add_concurrent_index :snippets, :content, name: INDEX_NAME, using: :gin, opclass: { content: :gin_trgm_ops }
end
def down
remove_concurrent_index_by_name(:snippets, INDEX_NAME)
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_09_26_041216) do
ActiveRecord::Schema.define(version: 2019_09_27_074328) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
......@@ -3319,6 +3319,7 @@ ActiveRecord::Schema.define(version: 2019_09_26_041216) do
t.text "description"
t.text "description_html"
t.index ["author_id"], name: "index_snippets_on_author_id"
t.index ["content"], name: "index_snippets_on_content_trigram", opclass: :gin_trgm_ops, using: :gin
t.index ["file_name"], name: "index_snippets_on_file_name_trigram", opclass: :gin_trgm_ops, using: :gin
t.index ["project_id"], name: "index_snippets_on_project_id"
t.index ["title"], name: "index_snippets_on_title_trigram", opclass: :gin_trgm_ops, using: :gin
......
......@@ -93,6 +93,17 @@ To check these feature flag values, please ask administrator to execute the foll
> Feature.enable(:ci_use_merge_request_ref) # Enable the feature flag.
```
### Intermittently pipelines fail by `fatal: reference is not a tree:` error
Since pipelines for merged results are a run on a merge ref of a merge request
(`refs/merge-requests/<iid>/merge`), the git-reference could be overwritten at an
unexpected timing, for example, when a source or target branch is advanced.
In this case, the pipeline fails because of `fatal: reference is not a tree:` error,
which indicates that the checkout-SHA is not found in the merge ref.
This behavior was improved at GitLab 12.4 by introducing [Persistent pipeline refs](../../pipelines.md#persistent-pipeline-refs).
You should be able to create pipelines at any timings without concerning the error.
## Using Merge Trains **(PREMIUM)**
By enabling [Pipelines for merged results](#pipelines-for-merged-results-premium),
......
......@@ -405,3 +405,44 @@ branches, avoiding untrusted code to be executed on the protected runner and
preserving deployment keys and other credentials from being unintentionally
accessed. In order to ensure that jobs intended to be executed on protected
runners will not use regular runners, they must be tagged accordingly.
## Persistent pipeline refs
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/17043) in GitLab 12.4.
Previously, you'd have encountered unexpected pipeline failures when you force-pushed
a branch to its remote repository. To illustrate the problem, suppose you've had the current workflow:
1. A user creates a feature branch named `example` and pushes it to a remote repository.
1. A new pipeline starts running on the `example` branch.
1. A user rebases the `example` branch on the latest `master` branch and force-pushes it to its remote repository.
1. A new pipeline starts running on the `example` branch again, however,
the previous pipeline (2) fails because of `fatal: reference is not a tree:` error.
This is because the previous pipeline cannot find a checkout-SHA (which associated with the pipeline record)
from the `example` branch that the commit history has already been overwritten by the force-push.
Similarly, [Pipelines for merged results](merge_request_pipelines/pipelines_for_merged_results/index.md)
might have failed intermittently due to [the same reason](merge_request_pipelines/pipelines_for_merged_results/index.md#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error).
As of GitLab 12.4, we've improved this behavior by persisting pipeline refs exclusively.
To illustrate its life cycle:
1. A pipeline is created on a feature branch named `example`.
1. A persistent pipeline ref is created at `refs/pipelines/<pipeline-id>`,
which retains the checkout-SHA of the associated pipeline record.
This persistent ref stays intact during the pipeline execution,
even if the commit history of the `example` branch has been overwritten by force-push.
1. GitLab Runner fetches the persistent pipeline ref and gets source code from the checkout-SHA.
1. When the pipeline finished, its persistent ref is cleaned up in a background process.
NOTE: **NOTE**: At this moment, this feature is off dy default and can be manually enabled
by enabling `depend_on_persistent_pipeline_ref` feature flag, however, we'd remove this
feature flag and make it enabled by deafult by the day we release 12.4 _if we don't find any issues_.
If you'd be interested in manually turning on this behavior, please ask the administrator
to execute the following commands in rails console.
```shell
> sudo gitlab-rails console # Login to Rails console of GitLab instance.
> project = Project.find_by_full_path('namespace/project-name') # Get the project instance.
> Feature.enable(:depend_on_persistent_pipeline_ref, project) # Enable the feature flag.
```
......@@ -1246,8 +1246,8 @@ Read how caching works and find out some good practices in the
[caching dependencies documentation](../caching/index.md).
`cache` is used to specify a list of files and directories which should be
cached between jobs. You can only use paths that are within the project
workspace.
cached between jobs. You can only use paths that are within the local working
copy.
If `cache` is defined outside the scope of jobs, it means it is set
globally and all jobs will use that definition.
......@@ -1417,7 +1417,7 @@ be available for download in the GitLab UI.
#### `artifacts:paths`
You can only use paths that are within the project workspace.
You can only use paths that are within the local working copy.
Wildcards can be used that follow the [glob](https://en.wikipedia.org/wiki/Glob_(programming)) patterns and [filepath.Match](https://golang.org/pkg/path/filepath/#Match).
To pass artifacts between different jobs, see [dependencies](#dependencies).
......@@ -2296,7 +2296,7 @@ or public project, or template is allowed.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/56836) in GitLab 11.9.
Nested includes allow you to compose a set of includes.
A total of 50 includes is allowed.
A total of 100 includes is allowed.
Duplicate includes are considered a configuration error.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/28212) in GitLab 12.4.
......@@ -2738,14 +2738,14 @@ unspecified, the default from project settings will be used.
There are three possible values: `clone`, `fetch`, and `none`.
`clone` is the slowest option. It clones the repository from scratch for every
job, ensuring that the project workspace is always pristine.
job, ensuring that the local working copy is always pristine.
```yaml
variables:
GIT_STRATEGY: clone
```
`fetch` is faster as it re-uses the project workspace (falling back to `clone`
`fetch` is faster as it re-uses the local working copy (falling back to `clone`
if it doesn't exist). `git clean` is used to undo any changes made by the last
job, and `git fetch` is used to retrieve commits made since the last job ran.
......@@ -2754,11 +2754,11 @@ variables:
GIT_STRATEGY: fetch
```
`none` also re-uses the project workspace, but skips all Git operations
`none` also re-uses the local working copy, but skips all Git operations
(including GitLab Runner's pre-clone script, if present). It is mostly useful
for jobs that operate exclusively on artifacts (e.g., `deploy`). Git repository
data may be present, but it is certain to be out of date, so you should only
rely on files brought into the project workspace from cache or artifacts.
rely on files brought into the local working copy from cache or artifacts.
```yaml
variables:
......
......@@ -62,8 +62,7 @@ Please help other GitLab users when you can.
The methods people will use to seek help can be found on the [getting help page](https://about.gitlab.com/get-help/).
Sign up for the mailing list, answer GitLab questions on StackOverflow or
respond in the IRC channel. You can also sign up on [CodeTriage](https://www.codetriage.com/gitlabhq/gitlabhq) to help with
the remaining issues on the GitHub issue tracker.
respond in the IRC channel.
## I want to contribute
......
......@@ -84,7 +84,7 @@ For example, only two pipelines will be created per day if:
To change the Sidekiq worker's frequency:
1. Edit the `gitlab_rails['pipeline_schedule_worker_cron']` value in your instance's `gitlab.rb` file.
1. [Restart GitLab](../../../administration/restart_gitlab.md).
1. [Reconfigure GitLab](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
For GitLab.com, refer to the [dedicated settings page](../../gitlab_com/index.md#cron-jobs).
......
......@@ -21,8 +21,8 @@ from GitLab in a job.
There are two options. Using:
- `git clone`, which is slower since it clones the repository from scratch
for every job, ensuring that the project workspace is always pristine.
- `git fetch`, which is faster as it re-uses the project workspace (falling
for every job, ensuring that the local working copy is always pristine.
- `git fetch`, which is faster as it re-uses the local working copy (falling
back to clone if it doesn't exist).
The default Git strategy can be overridden by the [GIT_STRATEGY variable](../../../ci/yaml/README.md#git-strategy)
......
......@@ -7,7 +7,7 @@ module Gitlab
class Mapper
include Gitlab::Utils::StrongMemoize
MAX_INCLUDES = 50
MAX_INCLUDES = 100
FILE_CLASSES = [
External::File::Remote,
......
......@@ -38,6 +38,10 @@ module Gitlab
gon.current_user_fullname = current_user.name
gon.current_user_avatar_url = current_user.avatar_url
end
# Initialize gon.features with any flags that should be
# made globally available to the frontend
push_frontend_feature_flag(:suppress_ajax_navigation_errors, default_enabled: true)
end
# Exposes the state of a feature flag to the frontend code.
......
......@@ -14,6 +14,10 @@ describe Boards::ListsController do
end
describe 'GET index' do
before do
create(:list, board: board)
end
it 'returns a successful 200 response' do
read_board_list user: user, board: board
......@@ -22,27 +26,22 @@ describe Boards::ListsController do
end
it 'returns a list of board lists' do
create(:list, board: board)
read_board_list user: user, board: board
expect(response).to match_response_schema('lists')
expect(json_response.length).to eq 3
end
it 'avoids n+1 queries when serializing lists' do
list_1 = create(:list, board: board)
list_1.update_preferences_for(user, { collapsed: true })
control_count = ActiveRecord::QueryRecorder.new { read_board_list user: user, board: board }.count
list_2 = create(:list, board: board)
list_2.update_preferences_for(user, { collapsed: true })
context 'when another user has list preferences' do
before do
board.lists.first.update_preferences_for(guest, collapsed: true)
end
list_3 = create(:list, board: board)
list_3.update_preferences_for(user, { collapsed: true })
it 'returns the complete list of board lists' do
read_board_list user: user, board: board
expect { read_board_list user: user, board: board }.not_to exceed_query_limit(control_count)
expect(json_response.length).to eq 3
end
end
context 'with unauthorized user' do
......
# frozen_string_literal: true
require 'spec_helper'
describe 'Issue page tabs', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
let(:issue) { create(:issue, author: user, assignees: [user], project: project) }
describe 'discussions tab counter' do
before do
stub_licensed_features(design_management: true)
stub_feature_flags(design_management_flag: true)
allow(Ability).to receive(:allowed?) { true }
end
subject do
sign_in(user)
visit project_issue_path(project, issue)
wait_for_requests
find('#discussion')
end
context 'new issue' do
it 'displays count of 0' do
is_expected.to have_content('Discussion 0')
end
end
context 'issue with 2 system notes and 1 discussion' do
let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: project, note: "This is good") }
before do
create(:system_note, noteable: issue, project: project, author: user, note: 'description updated')
create(:system_note, noteable: issue, project: project, author: user, note: 'description updated')
end
it 'displays count of 1' do
is_expected.to have_content('Discussion 1')
end
context 'with 1 reply' do
before do
create(:note, noteable: issue, in_reply_to: discussion, discussion_id: discussion.discussion_id, note: 'I also think this is good')
end
it 'displays count of 2' do
is_expected.to have_content('Discussion 2')
end
end
end
end
end
import suppressAjaxErrorsDuringNavigation from '~/lib/utils/suppress_ajax_errors_during_navigation';
import waitForPromises from 'helpers/wait_for_promises';
describe('suppressAjaxErrorsDuringNavigation', () => {
const OTHER_ERR_CODE = 'foo';
const NAV_ERR_CODE = 'ECONNABORTED';
it.each`
isFeatureFlagEnabled | isUserNavigating | code
${false} | ${false} | ${OTHER_ERR_CODE}
${false} | ${false} | ${NAV_ERR_CODE}
${false} | ${true} | ${OTHER_ERR_CODE}
${false} | ${true} | ${NAV_ERR_CODE}
${true} | ${false} | ${OTHER_ERR_CODE}
${true} | ${false} | ${NAV_ERR_CODE}
${true} | ${true} | ${OTHER_ERR_CODE}
`('should return a rejected Promise', ({ isFeatureFlagEnabled, isUserNavigating, code }) => {
const err = { code };
const actual = suppressAjaxErrorsDuringNavigation(err, isUserNavigating, isFeatureFlagEnabled);
return expect(actual).rejects.toBe(err);
});
it('should return a Promise that never resolves', () => {
const err = { code: NAV_ERR_CODE };
const actual = suppressAjaxErrorsDuringNavigation(err, true, true);
const thenCallback = jest.fn();
const catchCallback = jest.fn();
actual.then(thenCallback).catch(catchCallback);
return waitForPromises().then(() => {
expect(thenCallback).not.toHaveBeenCalled();
expect(catchCallback).not.toHaveBeenCalled();
});
});
});
......@@ -236,8 +236,15 @@ describe('Frequent Items App Component', () => {
.then(() => {
expect(vm.$el.querySelector('.loading-animation')).toBeDefined();
})
// This test waits for multiple ticks in order to allow the responses to
// propagate through each interceptor installed on the Axios instance.
// This shouldn't be necessary; this test should be refactored to avoid this.
// https://gitlab.com/gitlab-org/gitlab/issues/32479
.then(vm.$nextTick)
.then(vm.$nextTick)
.then(vm.$nextTick)
.then(() => {
expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe(
mockSearchedProjects.length,
......
......@@ -943,4 +943,14 @@ describe('common_utils', () => {
expect(commonUtils.isScopedLabel({ title: 'foobar' })).toBe(false);
});
});
describe('getDashPath', () => {
it('returns the path following /-/', () => {
expect(commonUtils.getDashPath('/some/-/url-with-dashes-/')).toEqual('url-with-dashes-/');
});
it('returns null when no path follows /-/', () => {
expect(commonUtils.getDashPath('/some/url')).toEqual(null);
});
});
});
......@@ -3079,6 +3079,12 @@ describe Ci::Build do
rescue StateMachines::InvalidTransition
end
it 'ensures pipeline ref existence' do
expect(job.pipeline.persistent_ref).to receive(:create).once
run_job_without_exception
end
shared_examples 'saves data on transition' do
it 'saves timeout' do
expect { job.run! }.to change { job.reload.ensure_metadata.timeout }.from(nil).to(expected_timeout)
......
# frozen_string_literal: true
require 'spec_helper'
describe Ci::PersistentRef do
it 'cleans up persistent refs after pipeline finished' do
pipeline = create(:ci_pipeline, :running)
expect(pipeline.persistent_ref).to receive(:delete).once
pipeline.succeed!
end
context '#exist?' do
subject { pipeline.persistent_ref.exist? }
let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
let(:project) { create(:project, :repository) }
let(:sha) { project.repository.commit.sha }
context 'when a persistent ref does not exist' do
it { is_expected.to eq(false) }
end
context 'when a persistent ref exists' do
before do
pipeline.persistent_ref.create
end
it { is_expected.to eq(true) }
end
end
context '#create' do
subject { pipeline.persistent_ref.create }
let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
let(:project) { create(:project, :repository) }
let(:sha) { project.repository.commit.sha }
context 'when a persistent ref does not exist' do
it 'creates a persistent ref' do
subject
expect(pipeline.persistent_ref).to be_exist
end
context 'when depend_on_persistent_pipeline_ref feature flag is disabled' do
before do
stub_feature_flags(depend_on_persistent_pipeline_ref: false)
end
it 'does not create a persistent ref' do
expect(project.repository).not_to receive(:create_ref)
subject
end
end
context 'when sha does not exist in the repository' do
let(:sha) { 'not-exist' }
it 'fails to create a persistent ref' do
subject
expect(pipeline.persistent_ref).not_to be_exist
end
end
end
context 'when a persistent ref already exists' do
before do
pipeline.persistent_ref.create
end
it 'does not create a persistent ref' do
expect(project.repository).not_to receive(:create_ref)
subject
end
end
end
context '#delete' do
subject { pipeline.persistent_ref.delete }
let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
let(:project) { create(:project, :repository) }
let(:sha) { project.repository.commit.sha }
context 'when a persistent ref exists' do
before do
pipeline.persistent_ref.create
end
it 'deletes the ref' do
expect { subject }.to change { pipeline.persistent_ref.exist? }
.from(true).to(false)
end
end
context 'when a persistent ref does not exist' do
it 'does not raise an error' do
expect { subject }.not_to raise_error
end
end
end
end
......@@ -1318,6 +1318,16 @@ describe Ci::Pipeline, :mailer do
let(:build_b) { create_build('build2', queued_at: 0) }
let(:build_c) { create_build('build3', queued_at: 0) }
%w[succeed! drop! cancel! skip!].each do |action|
context "when the pipeline recieved #{action} event" do
it 'deletes a persistent ref' do
expect(pipeline.persistent_ref).to receive(:delete).once
pipeline.public_send(action)
end
end
end
describe '#duration' do
context 'when multiple builds are finished' do
before do
......
......@@ -136,18 +136,6 @@ describe List do
expect(preferences).to be_persisted
expect(preferences.collapsed).to eq(true)
end
context 'when preferences are already loaded for user' do
it 'gets preloaded user preferences' do
fetched_list = described_class.where(id: list.id).with_preferences_for(user).first
expect(fetched_list).to receive(:preloaded_preferences_for).with(user).and_call_original
preferences = fetched_list.preferences_for(user)
expect(preferences.collapsed).to eq(true)
end
end
end
context 'when preferences for user does not exist' do
......
......@@ -207,5 +207,22 @@ describe Ci::BuildRunnerPresenter do
end
end
end
context 'when persistent pipeline ref exists' do
let(:project) { create(:project, :repository) }
let(:sha) { project.repository.commit.sha }
let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
before do
pipeline.persistent_ref.create
end
it 'exposes the persistent pipeline ref' do
is_expected
.to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
"+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Boards::ListsController do
describe '#index' do
let(:board) { create(:board) }
let(:user) { board.project.owner }
it 'does not have N+1 queries' do
login_as(user)
# First request has more queries because we create the default `backlog` list
get board_lists_path(board)
create(:list, board: board)
control_count = ActiveRecord::QueryRecorder.new { get board_lists_path(board) }.count
create_list(:list, 5, board: board)
expect { get board_lists_path(board) }.not_to exceed_query_limit(control_count)
end
end
end
......@@ -422,6 +422,18 @@ describe Ci::ProcessPipelineService, '#execute' do
end
end
context 'when an exception is raised during a persistent ref creation' do
before do
successful_build('test', stage_idx: 0)
allow_any_instance_of(Ci::PersistentRef).to receive(:delete_refs) { raise ArgumentError }
end
it 'process the pipeline' do
expect { process_pipeline }.not_to raise_error
end
end
context 'when there are manual action in earlier stages' do
context 'when first stage has only optional manual actions' do
before do
......@@ -907,6 +919,10 @@ describe Ci::ProcessPipelineService, '#execute' do
create(:ci_build, :created, pipeline: pipeline, name: name, **opts)
end
def successful_build(name, **opts)
create(:ci_build, :success, pipeline: pipeline, name: name, **opts)
end
def delayed_options
{ when: 'delayed', options: { script: %w(echo), start_in: '1 minute' } }
end
......
......@@ -501,6 +501,22 @@ module Ci
expect(pending_job).to be_archived_failure
end
end
context 'when an exception is raised during a persistent ref creation' do
before do
allow_any_instance_of(Ci::PersistentRef).to receive(:exist?) { false }
allow_any_instance_of(Ci::PersistentRef).to receive(:create_ref) { raise ArgumentError }
end
subject { execute(specific_runner, {}) }
it 'picks the build' do
expect(subject).to eq(pending_job)
pending_job.reload
expect(pending_job).to be_running
end
end
end
describe '#register_success' do
......
......@@ -2029,6 +2029,15 @@ axios@^0.19.0:
follow-redirects "1.5.10"
is-buffer "^2.0.2"
babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
dependencies:
chalk "^1.1.3"
esutils "^2.0.2"
js-tokens "^3.0.2"
babel-eslint@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed"
......@@ -2638,7 +2647,7 @@ camelcase@^4.0.0, camelcase@^4.1.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
camelcase@^5.0.0, camelcase@^5.3.1:
camelcase@^5.0.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
......@@ -2686,7 +2695,7 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^1.1.1:
chalk@^1.1.1, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
......@@ -3401,29 +3410,38 @@ css-b64-images@~0.2.5:
resolved "https://registry.yarnpkg.com/css-b64-images/-/css-b64-images-0.2.5.tgz#42005d83204b2b4a5d93b6b1a5644133b5927a02"
integrity sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=
css-loader@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.2.0.tgz#bb570d89c194f763627fcf1f80059c6832d009b2"
integrity sha512-QTF3Ud5H7DaZotgdcJjGMvyDj5F3Pn1j/sC6VBEOVp94cbwqyIBdcs/quzj4MC1BKQSrTpQznegH/5giYbhnCQ==
css-loader@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.1.tgz#6885bb5233b35ec47b006057da01cc640b6b79fe"
integrity sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==
dependencies:
camelcase "^5.3.1"
cssesc "^3.0.0"
icss-utils "^4.1.1"
loader-utils "^1.2.3"
normalize-path "^3.0.0"
postcss "^7.0.17"
postcss-modules-extract-imports "^2.0.0"
postcss-modules-local-by-default "^3.0.2"
postcss-modules-scope "^2.1.0"
postcss-modules-values "^3.0.0"
postcss-value-parser "^4.0.0"
schema-utils "^2.0.0"
babel-code-frame "^6.26.0"
css-selector-tokenizer "^0.7.0"
icss-utils "^2.1.0"
loader-utils "^1.0.2"
lodash "^4.17.11"
postcss "^6.0.23"
postcss-modules-extract-imports "^1.2.0"
postcss-modules-local-by-default "^1.2.0"
postcss-modules-scope "^1.1.0"
postcss-modules-values "^1.3.0"
postcss-value-parser "^3.3.0"
source-list-map "^2.0.0"
css-selector-parser@^1.3:
version "1.3.0"
resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.3.0.tgz#5f1ad43e2d8eefbfdc304fcd39a521664943e3eb"
integrity sha1-XxrUPi2O77/cME/NOaUhZklD4+s=
css-selector-tokenizer@^0.7.0:
version "0.7.1"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d"
integrity sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==
dependencies:
cssesc "^0.1.0"
fastparse "^1.1.1"
regexpu-core "^1.0.0"
css@^2.1.0:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
......@@ -3434,6 +3452,11 @@ css@^2.1.0:
source-map-resolve "^0.5.2"
urix "^0.1.0"
cssesc@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=
cssesc@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703"
......@@ -5041,6 +5064,11 @@ fast-levenshtein@~2.0.4:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
fastparse@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
fault@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa"
......@@ -6092,12 +6120,17 @@ iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.22, iconv-lite@^0.4.4:
dependencies:
safer-buffer ">= 2.1.2 < 3"
icss-utils@^4.0.0, icss-utils@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==
icss-replace-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=
icss-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962"
integrity sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=
dependencies:
postcss "^7.0.14"
postcss "^6.0.1"
ieee754@1.1.8, ieee754@^1.1.4:
version "1.1.8"
......@@ -7268,6 +7301,11 @@ js-levenshtein@^1.1.3:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-tokens@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.13.1:
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
......@@ -9445,38 +9483,36 @@ postcss-media-query-parser@^0.2.3:
resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244"
integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=
postcss-modules-extract-imports@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e"
integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==
postcss-modules-extract-imports@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz#dc87e34148ec7eab5f791f7cd5849833375b741a"
integrity sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==
dependencies:
postcss "^7.0.5"
postcss "^6.0.1"
postcss-modules-local-by-default@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915"
integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==
postcss-modules-local-by-default@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=
dependencies:
icss-utils "^4.1.1"
postcss "^7.0.16"
postcss-selector-parser "^6.0.2"
postcss-value-parser "^4.0.0"
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
postcss-modules-scope@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz#ad3f5bf7856114f6fcab901b0502e2a2bc39d4eb"
integrity sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==
postcss-modules-scope@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A=
dependencies:
postcss "^7.0.6"
postcss-selector-parser "^6.0.0"
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
postcss-modules-values@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10"
integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==
postcss-modules-values@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=
dependencies:
icss-utils "^4.0.0"
postcss "^7.0.6"
icss-replace-symbols "^1.1.0"
postcss "^6.0.1"
postcss-reporter@^6.0.1:
version "6.0.1"
......@@ -9533,7 +9569,7 @@ postcss-selector-parser@^5.0.0:
indexes-of "^1.0.1"
uniq "^1.0.1"
postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
postcss-selector-parser@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c"
integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==
......@@ -9547,7 +9583,7 @@ postcss-syntax@^0.36.2:
resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c"
integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==
postcss-value-parser@^3.3.1:
postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
......@@ -9557,7 +9593,7 @@ postcss-value-parser@^4.0.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz#99a983d365f7b2ad8d0f9b8c3094926eab4b936d"
integrity sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==
postcss@^6.0.14:
postcss@^6.0.1, postcss@^6.0.14, postcss@^6.0.23:
version "6.0.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
......@@ -9566,7 +9602,7 @@ postcss@^6.0.14:
source-map "^0.6.1"
supports-color "^5.4.0"
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7:
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.7:
version "7.0.18"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.18.tgz#4b9cda95ae6c069c67a4d933029eddd4838ac233"
integrity sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g==
......@@ -10138,7 +10174,7 @@ regenerate-unicode-properties@^8.1.0:
dependencies:
regenerate "^1.4.0"
regenerate@^1.4.0:
regenerate@^1.2.1, regenerate@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
......@@ -10163,6 +10199,15 @@ regexpp@^2.0.1:
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
regexpu-core@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
integrity sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=
dependencies:
regenerate "^1.2.1"
regjsgen "^0.2.0"
regjsparser "^0.1.4"
regexpu-core@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6"
......@@ -10190,11 +10235,23 @@ registry-url@^3.0.3:
dependencies:
rc "^1.0.1"
regjsgen@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=
regjsgen@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd"
integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==
regjsparser@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=
dependencies:
jsesc "~0.5.0"
regjsparser@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册