Add latest changes from gitlab-org/gitlab@master
|
@ -1 +1 @@
|
|||
0a03f045e065b9e7a157322fbe486e1f02fd8617
|
||||
072f01c9a020b2b49c222a338349555b2e807384
|
||||
|
|
2
Gemfile
|
@ -171,7 +171,7 @@ gem 'asciidoctor-kroki', '~> 0.5.0', require: false
|
|||
gem 'rouge', '~> 3.30.0'
|
||||
gem 'truncato', '~> 0.7.11'
|
||||
gem 'bootstrap_form', '~> 4.2.0'
|
||||
gem 'nokogiri', '~> 1.13.6'
|
||||
gem 'nokogiri', '~> 1.13.0'
|
||||
gem 'escape_utils', '~> 1.1'
|
||||
|
||||
# Calendar rendering
|
||||
|
|
|
@ -846,7 +846,7 @@ GEM
|
|||
netrc (0.11.0)
|
||||
nio4r (2.5.8)
|
||||
no_proxy_fix (0.1.2)
|
||||
nokogiri (1.13.7)
|
||||
nokogiri (1.13.8)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
notiffany (0.1.3)
|
||||
|
@ -1639,7 +1639,7 @@ DEPENDENCIES
|
|||
multi_json (~> 1.14.1)
|
||||
net-ldap (~> 0.16.3)
|
||||
net-ntp
|
||||
nokogiri (~> 1.13.6)
|
||||
nokogiri (~> 1.13.0)
|
||||
oauth2 (~> 2.0)
|
||||
octokit (~> 4.15)
|
||||
ohai (~> 16.10)
|
||||
|
|
|
@ -30,7 +30,7 @@ export default {
|
|||
|
||||
computed: {
|
||||
mergeError() {
|
||||
const mergeError = this.mr.mergeError ? stripHtml(this.mr.mergeError, ' ').trim() : '';
|
||||
const mergeError = this.prepareMergeError(this.mr.mergeError);
|
||||
|
||||
return sprintf(
|
||||
s__('mrWidget|%{mergeError}.'),
|
||||
|
@ -76,6 +76,13 @@ export default {
|
|||
this.refresh();
|
||||
}
|
||||
},
|
||||
prepareMergeError(mergeError) {
|
||||
return mergeError
|
||||
? stripHtml(mergeError, ' ')
|
||||
.replace(/(\.$|\s+)/g, ' ')
|
||||
.trim()
|
||||
: '';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -89,7 +96,9 @@ export default {
|
|||
<status-icon :show-disabled-button="true" status="warning" />
|
||||
<div class="media-body space-children">
|
||||
<span class="bold">
|
||||
<span v-if="mr.mergeError" class="has-error-message"> {{ mergeError }} </span>
|
||||
<span v-if="mr.mergeError" class="has-error-message" data-testid="merge-error">
|
||||
{{ mergeError }}
|
||||
</span>
|
||||
<span v-else> {{ s__('mrWidget|Merge failed.') }} </span>
|
||||
<span :class="{ 'has-custom-error': mr.mergeError }"> {{ timerText }} </span>
|
||||
</span>
|
||||
|
|
|
@ -2,35 +2,84 @@
|
|||
|
||||
module Branches
|
||||
class CreateService < BaseService
|
||||
def initialize(project, user = nil, params = {})
|
||||
super(project, user, params)
|
||||
|
||||
@errors = []
|
||||
end
|
||||
|
||||
def execute(branch_name, ref, create_default_branch_if_empty: true)
|
||||
create_default_branch if create_default_branch_if_empty && project.empty_repo?
|
||||
|
||||
result = ::Branches::ValidateNewService.new(project).execute(branch_name)
|
||||
result = branch_validation_service.execute(branch_name)
|
||||
|
||||
return result if result[:status] == :error
|
||||
|
||||
begin
|
||||
new_branch = repository.add_branch(current_user, branch_name, ref)
|
||||
rescue Gitlab::Git::CommandError => e
|
||||
return error("Failed to create branch '#{branch_name}': #{e}")
|
||||
create_branch(branch_name, ref)
|
||||
end
|
||||
|
||||
def bulk_create(branches)
|
||||
reset_errors
|
||||
|
||||
created_branches =
|
||||
branches
|
||||
.then { |branches| only_valid_branches(branches) }
|
||||
.then { |branches| create_branches(branches) }
|
||||
|
||||
return error(errors) if errors.present?
|
||||
|
||||
success(branches: created_branches)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :errors
|
||||
|
||||
def reset_errors
|
||||
@errors = []
|
||||
end
|
||||
|
||||
def only_valid_branches(branches)
|
||||
branches.select do |branch_name, _ref|
|
||||
result = branch_validation_service.execute(branch_name)
|
||||
|
||||
if result[:status] == :error
|
||||
errors << result[:message]
|
||||
next
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def create_branches(branches)
|
||||
branches.filter_map do |branch_name, ref|
|
||||
result = create_branch(branch_name, ref)
|
||||
|
||||
if result[:status] == :error
|
||||
errors << result[:message]
|
||||
next
|
||||
end
|
||||
|
||||
result[:branch]
|
||||
end
|
||||
end
|
||||
|
||||
def create_branch(branch_name, ref)
|
||||
new_branch = repository.add_branch(current_user, branch_name, ref)
|
||||
|
||||
if new_branch
|
||||
success(new_branch)
|
||||
success(branch: new_branch)
|
||||
else
|
||||
error("Failed to create branch '#{branch_name}': invalid reference name '#{ref}'")
|
||||
end
|
||||
rescue Gitlab::Git::CommandError => e
|
||||
error("Failed to create branch '#{branch_name}': #{e}")
|
||||
rescue Gitlab::Git::PreReceiveError => e
|
||||
Gitlab::ErrorTracking.log_exception(e, pre_receive_message: e.raw_message, branch_name: branch_name, ref: ref)
|
||||
error(e.message)
|
||||
end
|
||||
|
||||
def success(branch)
|
||||
super().merge(branch: branch)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_default_branch
|
||||
project.repository.create_file(
|
||||
current_user,
|
||||
|
@ -40,5 +89,9 @@ module Branches
|
|||
branch_name: project.default_branch_or_main
|
||||
)
|
||||
end
|
||||
|
||||
def branch_validation_service
|
||||
@branch_validation_service ||= ::Branches::ValidateNewService.new(project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: pull_mirror_bulk_branches
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93211
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368797
|
||||
milestone: '15.2'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: false
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366741
|
|||
milestone: '15.2'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
@ -572,7 +572,7 @@ and after that you also need two extra steps.
|
|||
postgresql['md5_auth_cidr_addresses'] = ['<primary_site_ip>/32', '<secondary_site_ip>/32']
|
||||
|
||||
# Every secondary site needs to have its own slot so specify the number of secondary sites you're going to have
|
||||
postgresql['max_replication_slots'] = 1
|
||||
# postgresql['max_replication_slots'] = 1 # Set this to be the number of Geo secondary nodes if you have more than one
|
||||
|
||||
##
|
||||
## Disable automatic database migrations temporarily
|
||||
|
|
|
@ -235,9 +235,8 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
|
|||
|
||||
##
|
||||
## Replication settings
|
||||
## - set this to be the number of Geo secondary nodes you have
|
||||
##
|
||||
postgresql['max_replication_slots'] = 1
|
||||
# postgresql['max_replication_slots'] = 1 # Set this to be the number of Geo secondary nodes if you have more than one
|
||||
# postgresql['max_wal_senders'] = 10
|
||||
# postgresql['wal_keep_segments'] = 10
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ If you installed GitLab using the Omnibus packages (highly recommended):
|
|||
|
||||
1. [Install GitLab Enterprise Edition](https://about.gitlab.com/install/) on the nodes that serve as the **secondary** site. **Do not create an account or log in** to the new **secondary** site. The **GitLab version must match** across primary and secondary sites.
|
||||
1. [Add the GitLab License](../../../user/admin_area/license.md) on the **primary** site to unlock Geo. The license must be for [GitLab Premium](https://about.gitlab.com/pricing/) or higher.
|
||||
1. [Confirm network connectivity](../index.md#firewall-rules) between the **primary** and **secondary** site.
|
||||
1. [Set up the database replication](database.md) (`primary (read-write) <-> secondary (read-only)` topology).
|
||||
1. [Configure fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md). This step is required and needs to be done on **both** the **primary** and **secondary** sites.
|
||||
1. [Configure GitLab](../replication/configuration.md) to set the **primary** and **secondary** sites.
|
||||
|
|
|
@ -306,7 +306,7 @@ Project.find_each do |p|
|
|||
end
|
||||
```
|
||||
|
||||
## Bulk update to change all the Jira integrations to Jira instance-level values
|
||||
### Bulk update to change all the Jira integrations to Jira instance-level values
|
||||
|
||||
To change all Jira project to use the instance-level integration settings:
|
||||
|
||||
|
@ -321,6 +321,25 @@ To change all Jira project to use the instance-level integration settings:
|
|||
|
||||
1. Modify and save again the instance-level integration from the UI to propagate the changes to all the group-level and project-level integrations.
|
||||
|
||||
### Check if Jira Cloud is linked to a namespace
|
||||
|
||||
```ruby
|
||||
JiraConnectSubscription.where(namespace: Namespace.by_path('group/subgroup'))
|
||||
```
|
||||
|
||||
### Check if Jira Cloud is linked to a project
|
||||
|
||||
```ruby
|
||||
Project.find_by_full_path('path/to/project').jira_subscription_exists?
|
||||
```
|
||||
|
||||
### Check if Jira Cloud URL is linked to any namespace
|
||||
|
||||
```ruby
|
||||
installation = JiraConnectInstallation.find_by_base_url("https://customer_name.atlassian.net")
|
||||
installation.subscriptions
|
||||
```
|
||||
|
||||
### Bulk update to disable the Slack Notification service
|
||||
|
||||
To disable notifications for all projects that have Slack service enabled, do:
|
||||
|
|
|
@ -259,15 +259,16 @@ end
|
|||
|
||||
### Verify the MR was deployed and the index exists in production
|
||||
|
||||
You can verify if the MR was deployed to GitLab.com by executing
|
||||
`/chatops run auto_deploy status <merge_sha>`. To verify existence of
|
||||
the index, you can:
|
||||
You can verify if the post-deploy migration was executed on GitLab.com by:
|
||||
|
||||
- Executing `/chatops run auto_deploy status <merge_sha>`. If the output returns `db/gprd`,
|
||||
the post-deploy migration has been executed in the production database. More details in this
|
||||
[guide](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/post_deploy_migration/readme.md#how-to-determine-if-a-post-deploy-migration-has-been-executed-on-gitlabcom).
|
||||
- Use a meta-command in #database-lab, such as: `\d <index_name>`.
|
||||
- Ensure that the index is not [`invalid`](https://www.postgresql.org/docs/12/sql-createindex.html#:~:text=The%20psql%20%5Cd%20command%20will%20report%20such%20an%20index%20as%20INVALID).
|
||||
- Ask someone in #database to check if the index exists.
|
||||
- With proper access, you can also verify directly on production or in a
|
||||
production clone.
|
||||
production clone.
|
||||
|
||||
### Add a migration to create the index synchronously
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@ This however skips post deployment migrations:
|
|||
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bundle exec rake db:migrate
|
||||
```
|
||||
|
||||
For GitLab.com, these migrations are executed on a daily basis at the discretion of
|
||||
release managers through the
|
||||
[post-deploy migration pipeline](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/post_deploy_migration/readme.md).
|
||||
|
||||
## Deployment Integration
|
||||
|
||||
Say you're using Chef for deploying new versions of GitLab and you'd like to run
|
||||
|
|
|
@ -247,9 +247,9 @@ Include in the MR description:
|
|||
- Making numerous SQL queries per record in a dataset.
|
||||
- Review queries (for example, make sure batch sizes are fine)
|
||||
- Because execution time can be longer than for a regular migration,
|
||||
it's suggested to treat background migrations as post migrations:
|
||||
place them in `db/post_migrate` instead of `db/migrate`. Keep in mind
|
||||
that post migrations are executed post-deployment in production.
|
||||
it's suggested to treat background migrations as
|
||||
[post migrations](migration_style_guide.md#choose-an-appropriate-migration-type):
|
||||
place them in `db/post_migrate` instead of `db/migrate`.
|
||||
- If a migration [has tracking enabled](database/background_migrations.md#background-jobs-tracking),
|
||||
ensure `mark_all_as_succeeded` is called even if no work is done.
|
||||
- Check [timing guidelines for migrations](migration_style_guide.md#how-long-a-migration-should-take)
|
||||
|
|
|
@ -150,6 +150,8 @@ the page is rendered to HTML. There can be only **one** level 1 heading per page
|
|||
|
||||
- For each subsection, increment the heading level. In other words, increment the number of `#` characters
|
||||
in front of the heading.
|
||||
- Avoid headings greater than `H5` (`#####`). If you need more than five headings, move the topics to a new page instead.
|
||||
Headings greater than `H5` do not display in the right sidebar navigation.
|
||||
- Do not skip a level. For example: `##` > `####`.
|
||||
- Leave one blank line before and after the heading.
|
||||
|
||||
|
|
|
@ -46,8 +46,9 @@ work it needs to perform and how long it takes to complete:
|
|||
For example, you might have indices that enforce unique tuples, or that are needed for query performance in critical parts of the application. In cases where the migration would be unacceptably slow, however, a better option might be to guard the feature with a [feature flag](feature_flags/index.md)
|
||||
and perform a post-deployment migration instead. The feature can then be turned on after the migration finishes.
|
||||
1. [**Post-deployment migrations.**](database/post_deployment_migrations.md) These are Rails migrations in `db/post_migrate` and
|
||||
run _after_ new application code has been deployed (for GitLab.com after the production deployment has finished).
|
||||
They can be used for schema changes that aren't critical for the application to operate, or data migrations that take at most a few minutes.
|
||||
are run independently from the GitLab.com deployments. Pending post migrations are executed on a daily basis at the discretion
|
||||
of release manager through the [post-deploy migration pipeline](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/post_deploy_migration/readme.md#how-to-determine-if-a-post-deploy-migration-has-been-executed-on-gitlabcom).
|
||||
These migrations can be used for schema changes that aren't critical for the application to operate, or data migrations that take at most a few minutes.
|
||||
Common examples for schema changes that should run post-deploy include:
|
||||
- Clean-ups, like removing unused columns.
|
||||
- Adding non-critical indices on high-traffic tables.
|
||||
|
|
|
@ -137,3 +137,13 @@ See [Scan result policies](scan-result-policies.md).
|
|||
|
||||
See the [Category Direction page](https://about.gitlab.com/direction/protect/security_orchestration/)
|
||||
for more information on the product direction of security policies within GitLab.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Branch name does not follow the pattern `'update-policy-<timestamp>'`
|
||||
|
||||
When you create a new security policy or change an existing policy, a new branch is automatically created with the branch name following the pattern `update-policy-<timestamp>`. For example: `update-policy-1659094451`.
|
||||
|
||||
If you have group or instance push rules that do not allow branch name patterns that contain the text `update-policy-<timestamp>`, you will get an error that states `Branch name does not follow the pattern 'update-policy-<timestamp>'`.
|
||||
|
||||
The workaround is to amend your group or instance push rules to allow branches following the pattern `update-policy-` followed by an integer timestamp.
|
||||
|
|
|
@ -16,6 +16,9 @@ You can also configure your agent so the vulnerabilities are displayed with othe
|
|||
You can use operational container scanning
|
||||
to scan container images in your cluster for security vulnerabilities.
|
||||
|
||||
NOTE:
|
||||
In GitLab 15.0 and later, you do not need to install Starboard operator in the Kubernetes cluster.
|
||||
|
||||
To begin scanning all resources in your cluster, add a `starboard`
|
||||
configuration block to your agent configuration with a `cadence` field
|
||||
containing a CRON expression for when the scans will be run.
|
||||
|
|
|
@ -66,6 +66,9 @@ For most package types, the following credential types are valid:
|
|||
which prevents you from using a job token with internal projects. This bug only impacts self-managed
|
||||
GitLab instances.
|
||||
|
||||
NOTE:
|
||||
If you have not activated the "Packages" feature for your project at **Settings > General > Project features**, you will receive a 403 Forbidden response.
|
||||
|
||||
## Use GitLab CI/CD to build packages
|
||||
|
||||
You can use [GitLab CI/CD](../../../ci/index.md) to build packages.
|
||||
|
|
Before Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 48 KiB |
|
@ -36,13 +36,9 @@ To start your review:
|
|||
1. Select the **{comment}** **comment** icon in the gutter to expand the diff lines
|
||||
and display a comment box. In GitLab version 13.2 and later, you can
|
||||
[select multiple lines](#comment-on-multiple-lines).
|
||||
1. Write your first comment, and select **Start a review** below your comment:
|
||||
![Starting a review](img/mr_review_start.png)
|
||||
1. Continue adding comments to lines of code, and select the appropriate button after
|
||||
you write a comment:
|
||||
- **Add to review**: Keep this comment private and add to the current review.
|
||||
These review comments are marked **Pending** and are visible only to you.
|
||||
- **Add comment now**: Submits the specific comment as a regular comment instead of as part of the review.
|
||||
1. In the text area, write your first comment, then select **Start a review** below your comment.
|
||||
1. Continue adding comments to lines of code. After each comment, select **Add to review**.
|
||||
Comments made as part of a review are visible only to you until you submit your review.
|
||||
1. Optional. You can use [quick actions](../../quick_actions.md) inside review comments.
|
||||
The comment shows the actions to perform after publication, but does not perform them
|
||||
until you submit your review.
|
||||
|
@ -60,8 +56,12 @@ displays next to your name.
|
|||
You can submit your completed review in multiple ways:
|
||||
|
||||
- Use the `/submit_review` [quick action](../../quick_actions.md) in the text of a non-review comment.
|
||||
- When creating a review comment, select **Submit review**.
|
||||
- Scroll to the bottom of the screen and select **Submit review**.
|
||||
- Select **Finish review** and then **Submit review** in the footer at the bottom of the screen.
|
||||
|
||||
Selecting **Finish review** opens a modal window to add an optional comment to summarize your review.
|
||||
You can also include quick actions:
|
||||
|
||||
![Finish review with comment](img/mr_summary_comment_v15_3.png)
|
||||
|
||||
When you submit your review, GitLab:
|
||||
|
||||
|
@ -73,25 +73,25 @@ When you submit your review, GitLab:
|
|||
### Resolve or unresolve thread with a comment
|
||||
|
||||
Review comments can also resolve or unresolve [resolvable threads](../../../discussions/index.md#resolve-a-thread).
|
||||
When replying to a comment, a checkbox is displayed to resolve or unresolve
|
||||
the thread after publication.
|
||||
To resolve or unresolve a thread when replying to a comment:
|
||||
|
||||
![Resolve checkbox](img/mr_review_resolve.png)
|
||||
1. In the comment text area, write your comment.
|
||||
1. Select or clear **Resolve thread**.
|
||||
1. Select **Add comment now** or **Add to review**.
|
||||
|
||||
If a particular pending comment resolves or unresolves the thread, this is shown on the pending
|
||||
comment itself.
|
||||
Pending comments display information about the action to be taken when the comment is published:
|
||||
|
||||
![Resolve status](img/mr_review_resolve2.png)
|
||||
|
||||
![Unresolve status](img/mr_review_unresolve.png)
|
||||
- **{check-circle-filled}** Thread will be resolved.
|
||||
- **{check-circle}** Thread stays unresolved.
|
||||
|
||||
### Add a new comment
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8225) in GitLab 13.10.
|
||||
|
||||
If you have a review in progress, you are presented with the option to **Add to review**:
|
||||
If you have a review in progress, you can also add a comment from the **Overview** tab by selecting
|
||||
**Add to review**:
|
||||
|
||||
![New thread](img/mr_review_new_comment_v13_11.png)
|
||||
![New thread](img/mr_review_new_comment_v15_3.png)
|
||||
|
||||
### Approval Rule information for Reviewers **(PREMIUM)**
|
||||
|
||||
|
|
Before Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 4.3 KiB |
|
@ -74,7 +74,7 @@ to your project's settings through the gear icon in the top right, and then
|
|||
navigating to **Pages**. Select the **Remove pages** button to delete your Pages
|
||||
website.
|
||||
|
||||
![Remove pages](img/remove_pages.png)
|
||||
![Remove pages](img/remove_pages_v15_3.png)
|
||||
|
||||
## Subdomains of subdomains
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ GEM
|
|||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
netrc (0.11.0)
|
||||
nokogiri (1.13.6)
|
||||
nokogiri (1.13.8)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
octokit (4.21.0)
|
||||
|
|
|
@ -13,7 +13,7 @@ class StaticAnalysis
|
|||
# warning message so that GitLab backports don't fail.
|
||||
"Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade`",
|
||||
# https://github.com/mime-types/mime-types-data/pull/50#issuecomment-1060908930
|
||||
"Type application/netcdf is already registered as a variant of application/netcdf"
|
||||
"Type application/netcdf is already registered as a variant of application/netcdf."
|
||||
].freeze
|
||||
|
||||
Task = Struct.new(:command, :duration) do
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Value Stream Analytics', :js do
|
||||
include CycleAnalyticsHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:guest) { create(:user) }
|
||||
let_it_be(:stage_table_selector) { '[data-testid="vsa-stage-table"]' }
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe "GitLab Flavored Markdown" do
|
||||
include CycleAnalyticsHelpers
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project) }
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'User searches for commits', :js do
|
||||
include CycleAnalyticsHelpers
|
||||
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:sha) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
|
||||
let(:user) { create(:user) }
|
||||
|
|
|
@ -53,7 +53,31 @@ describe('MRWidgetFailedToMerge', () => {
|
|||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.mergeError).toBe('contains line breaks.');
|
||||
expect(wrapper.find('[data-testid="merge-error"]').text()).toBe('contains line breaks.');
|
||||
});
|
||||
|
||||
it('does not append an extra period', async () => {
|
||||
createComponent({ mr: { mergeError: 'contains a period.' } });
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.find('[data-testid="merge-error"]').text()).toBe('contains a period.');
|
||||
});
|
||||
|
||||
it('does not insert an extra space between the final character and the period', async () => {
|
||||
createComponent({ mr: { mergeError: 'contains a <a href="http://example.com">link</a>.' } });
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.find('[data-testid="merge-error"]').text()).toBe('contains a link.');
|
||||
});
|
||||
|
||||
it('removes extra spaces', async () => {
|
||||
createComponent({ mr: { mergeError: 'contains a lot of spaces .' } });
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.find('[data-testid="merge-error"]').text()).toBe('contains a lot of spaces.');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::PipelineEditorHelper do
|
||||
include CycleAnalyticsHelpers
|
||||
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
describe 'can_view_pipeline_editor?' do
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::CycleAnalytics::StageSummary do
|
||||
include CycleAnalyticsHelpers
|
||||
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
|
||||
let(:options) { { from: 1.day.ago } }
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'value stream analytics events' do
|
||||
include CycleAnalyticsHelpers
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository, public_builds: false) }
|
||||
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
|
||||
|
|
|
@ -2,17 +2,130 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Branches::CreateService do
|
||||
RSpec.describe Branches::CreateService, :use_clean_rails_redis_caching do
|
||||
subject(:service) { described_class.new(project, user) }
|
||||
|
||||
let_it_be(:project) { create(:project_empty_repo) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
describe '#bulk_create' do
|
||||
subject { service.bulk_create(branches) }
|
||||
|
||||
let_it_be(:project) { create(:project, :custom_repo, files: { 'foo/a.txt' => 'foo' }) }
|
||||
|
||||
let(:branches) { { 'branch' => 'master', 'another_branch' => 'master' } }
|
||||
|
||||
it 'creates two branches' do
|
||||
expect(subject[:status]).to eq(:success)
|
||||
expect(subject[:branches].map(&:name)).to match_array(%w[branch another_branch])
|
||||
|
||||
expect(project.repository.branch_exists?('branch')).to be_truthy
|
||||
expect(project.repository.branch_exists?('another_branch')).to be_truthy
|
||||
end
|
||||
|
||||
context 'when branches are empty' do
|
||||
let(:branches) { {} }
|
||||
|
||||
it 'is successful' do
|
||||
expect(subject[:status]).to eq(:success)
|
||||
expect(subject[:branches]).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when incorrect reference is provided' do
|
||||
let(:branches) { { 'new-feature' => 'unknown' } }
|
||||
|
||||
before do
|
||||
allow(project.repository).to receive(:add_branch).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns an error with a reference name' do
|
||||
err_msg = 'Failed to create branch \'new-feature\': invalid reference name \'unknown\''
|
||||
|
||||
expect(subject[:status]).to eq(:error)
|
||||
expect(subject[:message]).to match_array([err_msg])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when branch already exists' do
|
||||
let(:branches) { { 'master' => 'master' } }
|
||||
|
||||
it 'returns an error' do
|
||||
expect(subject[:status]).to eq(:error)
|
||||
expect(subject[:message]).to match_array(['Branch already exists'])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an ambiguous branch name is provided' do
|
||||
let(:branches) { { 'ambiguous/test' => 'master', 'ambiguous' => 'master' } }
|
||||
|
||||
it 'returns an error that branch could not be created' do
|
||||
err_msg = 'Failed to create branch \'ambiguous\': 13:reference is ambiguous.'
|
||||
|
||||
expect(subject[:status]).to eq(:error)
|
||||
expect(subject[:message]).to match_array([err_msg])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when PreReceiveError exception' do
|
||||
let(:branches) { { 'error' => 'master' } }
|
||||
|
||||
it 'logs and returns an error if there is a PreReceiveError exception' do
|
||||
error_message = 'pre receive error'
|
||||
raw_message = "GitLab: #{error_message}"
|
||||
pre_receive_error = Gitlab::Git::PreReceiveError.new(raw_message)
|
||||
|
||||
allow(project.repository).to receive(:add_branch).and_raise(pre_receive_error)
|
||||
|
||||
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
|
||||
pre_receive_error,
|
||||
pre_receive_message: raw_message,
|
||||
branch_name: 'error',
|
||||
ref: 'master'
|
||||
)
|
||||
|
||||
expect(subject[:status]).to eq(:error)
|
||||
expect(subject[:message]).to match_array([error_message])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when multiple errors occur' do
|
||||
let(:branches) { { 'master' => 'master', '' => 'master', 'failed_branch' => 'master' } }
|
||||
|
||||
it 'returns all errors' do
|
||||
allow(project.repository).to receive(:add_branch).with(user, 'failed_branch', 'master').and_return(false)
|
||||
|
||||
expect(subject[:status]).to eq(:error)
|
||||
expect(subject[:message]).to match_array(
|
||||
[
|
||||
'Branch already exists',
|
||||
'Branch name is invalid',
|
||||
"Failed to create branch 'failed_branch': invalid reference name 'master'"
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without N+1 for Redis cache' do
|
||||
let(:branches) { { 'branch1' => 'master', 'branch2' => 'master', 'branch3' => 'master' } }
|
||||
|
||||
it 'does not trigger Redis recreation' do
|
||||
project.repository.expire_branches_cache
|
||||
|
||||
control = RedisCommands::Recorder.new(pattern: ':branch_names:') { subject }
|
||||
|
||||
expect(control.by_command(:sadd).count).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
context 'when repository is empty' do
|
||||
it 'creates master branch' do
|
||||
service.execute('my-feature', 'master')
|
||||
result = service.execute('my-feature', 'master')
|
||||
|
||||
expect(result[:status]).to eq(:success)
|
||||
expect(result[:branch].name).to eq('my-feature')
|
||||
expect(project.repository.branch_exists?('master')).to be_truthy
|
||||
end
|
||||
|
||||
|
|
|
@ -161,7 +161,6 @@ RSpec.configure do |config|
|
|||
config.include LicenseHelpers
|
||||
config.include ActiveJob::TestHelper
|
||||
config.include ActiveSupport::Testing::TimeHelpers
|
||||
config.include CycleAnalyticsHelpers
|
||||
config.include FactoryBot::Syntax::Methods
|
||||
config.include FixtureHelpers
|
||||
config.include NonExistingRecordsHelpers
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module CycleAnalyticsHelpers
|
||||
include GitHelpers
|
||||
|
||||
def toggle_value_stream_dropdown
|
||||
page.find('[data-testid="dropdown-value-streams"]').click
|
||||
end
|
||||
|
@ -129,10 +127,6 @@ module CycleAnalyticsHelpers
|
|||
repository = project.repository
|
||||
oldrev = repository.commit(branch_name)&.sha || Gitlab::Git::BLANK_SHA
|
||||
|
||||
if Timecop.frozen?
|
||||
mock_gitaly_multi_action_dates(repository, commit_time)
|
||||
end
|
||||
|
||||
commit_shas = Array.new(count) do |index|
|
||||
commit_sha = repository.create_file(user, generate(:branch), "content", message: message, branch_name: branch_name)
|
||||
repository.commit(commit_sha)
|
||||
|
@ -241,23 +235,4 @@ module CycleAnalyticsHelpers
|
|||
pipeline: dummy_pipeline(project),
|
||||
protected: false)
|
||||
end
|
||||
|
||||
def mock_gitaly_multi_action_dates(repository, commit_time)
|
||||
allow(repository.raw).to receive(:multi_action).and_wrap_original do |m, user, kargs|
|
||||
new_date = commit_time || Time.now
|
||||
branch_update = m.call(user, **kargs)
|
||||
|
||||
if branch_update.newrev
|
||||
commit = rugged_repo(repository).rev_parse(branch_update.newrev)
|
||||
|
||||
branch_update.newrev = commit.amend(
|
||||
update_ref: "#{Gitlab::Git::BRANCH_REF_PREFIX}#{kargs[:branch_name]}",
|
||||
author: commit.author.merge(time: new_date),
|
||||
committer: commit.committer.merge(time: new_date)
|
||||
)
|
||||
end
|
||||
|
||||
branch_update
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_context 'Analytics fixtures shared context' do
|
||||
include CycleAnalyticsHelpers
|
||||
include JavaScriptFixturesHelpers
|
||||
|
||||
let_it_be(:group) { create(:group) }
|
||||
|
|