Commit 6a4ffad4 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 23d23711
...@@ -20,6 +20,7 @@ code_quality: ...@@ -20,6 +20,7 @@ code_quality:
variables: variables:
DOCKER_DRIVER: overlay2 DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: "" DOCKER_TLS_CERTDIR: ""
CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/security-products/codequality:12-5-stable"
script: script:
- | - |
if ! docker info &>/dev/null; then if ! docker info &>/dev/null; then
...@@ -27,11 +28,12 @@ code_quality: ...@@ -27,11 +28,12 @@ code_quality:
export DOCKER_HOST='tcp://localhost:2375' export DOCKER_HOST='tcp://localhost:2375'
fi fi
fi fi
- docker pull --quiet "$CODE_QUALITY_IMAGE"
- docker run - docker run
--env SOURCE_CODE="$PWD" --env SOURCE_CODE="$PWD"
--volume "$PWD":/code --volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock --volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:12-0-stable" /code "$CODE_QUALITY_IMAGE" /code
artifacts: artifacts:
reports: reports:
codequality: gl-code-quality-report.json codequality: gl-code-quality-report.json
......
...@@ -80,6 +80,15 @@ export default { ...@@ -80,6 +80,15 @@ export default {
} }
return ''; return '';
}, },
downloadPath() {
const data = JSON.stringify(this.requests);
const blob = new Blob([data], { type: 'text/plain' });
return window.URL.createObjectURL(blob);
},
downloadName() {
const fileName = this.requests[0].truncatedUrl;
return `${fileName}_perf_bar_${Date.now()}.json`;
},
}, },
mounted() { mounted() {
this.currentRequest = this.requestId; this.currentRequest = this.requestId;
...@@ -121,6 +130,9 @@ export default { ...@@ -121,6 +130,9 @@ export default {
<a :href="currentRequest.details.tracing.tracing_url">{{ s__('PerformanceBar|trace') }}</a> <a :href="currentRequest.details.tracing.tracing_url">{{ s__('PerformanceBar|trace') }}</a>
</div> </div>
<add-request v-on="$listeners" /> <add-request v-on="$listeners" />
<div v-if="currentRequest.details" id="peek-download" class="view">
<a :download="downloadName" :href="downloadPath">{{ s__('PerformanceBar|Download') }}</a>
</div>
<request-selector <request-selector
v-if="currentRequest" v-if="currentRequest"
:current-request="currentRequest" :current-request="currentRequest"
......
...@@ -40,16 +40,6 @@ export default { ...@@ -40,16 +40,6 @@ export default {
}, },
}, },
methods: { methods: {
truncatedUrl(requestUrl) {
const components = requestUrl.replace(/\/$/, '').split('/');
let truncated = components[components.length - 1];
if (truncated.match(/^\d+$/)) {
truncated = `${components[components.length - 2]}/${truncated}`;
}
return truncated;
},
glEmojiTag, glEmojiTag,
}, },
}; };
...@@ -63,7 +53,7 @@ export default { ...@@ -63,7 +53,7 @@ export default {
:value="request.id" :value="request.id"
class="qa-performance-bar-request" class="qa-performance-bar-request"
> >
{{ truncatedUrl(request.url) }} {{ request.truncatedUrl }}
<span v-if="request.hasWarnings">(!)</span> <span v-if="request.hasWarnings">(!)</span>
</option> </option>
</select> </select>
......
...@@ -5,9 +5,12 @@ export default class PerformanceBarStore { ...@@ -5,9 +5,12 @@ export default class PerformanceBarStore {
addRequest(requestId, requestUrl) { addRequest(requestId, requestUrl) {
if (!this.findRequest(requestId)) { if (!this.findRequest(requestId)) {
const shortUrl = PerformanceBarStore.truncateUrl(requestUrl);
this.requests.push({ this.requests.push({
id: requestId, id: requestId,
url: requestUrl, url: requestUrl,
truncatedUrl: shortUrl,
details: {}, details: {},
hasWarnings: false, hasWarnings: false,
}); });
...@@ -36,4 +39,20 @@ export default class PerformanceBarStore { ...@@ -36,4 +39,20 @@ export default class PerformanceBarStore {
canTrackRequest(requestUrl) { canTrackRequest(requestUrl) {
return this.requests.filter(request => request.url === requestUrl).length < 2; return this.requests.filter(request => request.url === requestUrl).length < 2;
} }
static truncateUrl(requestUrl) {
const [rootAndQuery] = requestUrl.split('#');
const [root, query] = rootAndQuery.split('?');
const components = root.replace(/\/$/, '').split('/');
let truncated = components[components.length - 1];
if (truncated.match(/^\d+$/)) {
truncated = `${components[components.length - 2]}/${truncated}`;
}
if (query) {
truncated += `?${query}`;
}
return truncated;
}
} }
...@@ -18,6 +18,7 @@ module ServiceParams ...@@ -18,6 +18,7 @@ module ServiceParams
:channels, :channels,
:color, :color,
:colorize_messages, :colorize_messages,
:comment_on_event_enabled,
:confidential_issues_events, :confidential_issues_events,
:default_irc_uri, :default_irc_uri,
:description, :description,
......
...@@ -31,6 +31,26 @@ module ServicesHelper ...@@ -31,6 +31,26 @@ module ServicesHelper
"#{event}_events" "#{event}_events"
end end
def service_event_action_field_name(action)
"#{action}_on_event_enabled"
end
def event_action_title(action)
case action
when "comment"
s_("ProjectService|Comment")
else
action.humanize
end
end
def event_action_description(action)
case action
when "comment"
s_("ProjectService|Comment will be posted on each event")
end
end
def service_save_button(service) def service_save_button(service)
button_tag(class: 'btn btn-success', type: 'submit', disabled: service.deprecated?, data: { qa_selector: 'save_changes_button' }) do button_tag(class: 'btn btn-success', type: 'submit', disabled: service.deprecated?, data: { qa_selector: 'save_changes_button' }) do
icon('spinner spin', class: 'hidden js-btn-spinner') + icon('spinner spin', class: 'hidden js-btn-spinner') +
......
...@@ -32,6 +32,10 @@ class JiraService < IssueTrackerService ...@@ -32,6 +32,10 @@ class JiraService < IssueTrackerService
%w(commit merge_request) %w(commit merge_request)
end end
def self.supported_event_actions
%w(comment)
end
# {PROJECT-KEY}-{NUMBER} Examples: JIRA-1, PROJECT-1 # {PROJECT-KEY}-{NUMBER} Examples: JIRA-1, PROJECT-1
def self.reference_pattern(only_long: true) def self.reference_pattern(only_long: true)
@reference_pattern ||= /(?<issue>\b#{Gitlab::Regex.jira_issue_key_regex})/ @reference_pattern ||= /(?<issue>\b#{Gitlab::Regex.jira_issue_key_regex})/
...@@ -268,19 +272,27 @@ class JiraService < IssueTrackerService ...@@ -268,19 +272,27 @@ class JiraService < IssueTrackerService
return unless client_url.present? return unless client_url.present?
jira_request do jira_request do
remote_link = find_remote_link(issue, remote_link_props[:object][:url]) create_issue_link(issue, remote_link_props)
if remote_link create_issue_comment(issue, message)
remote_link.save!(remote_link_props)
elsif issue.comments.build.save!(body: message)
new_remote_link = issue.remotelink.build
new_remote_link.save!(remote_link_props)
end
log_info("Successfully posted", client_url: client_url) log_info("Successfully posted", client_url: client_url)
"SUCCESS: Successfully posted to #{client_url}." "SUCCESS: Successfully posted to #{client_url}."
end end
end end
def create_issue_link(issue, remote_link_props)
remote_link = find_remote_link(issue, remote_link_props[:object][:url])
remote_link ||= issue.remotelink.build
remote_link.save!(remote_link_props)
end
def create_issue_comment(issue, message)
return unless comment_on_event_enabled
issue.comments.build.save!(body: message)
end
def find_remote_link(issue, url) def find_remote_link(issue, url)
links = jira_request { issue.remotelink.all } links = jira_request { issue.remotelink.all }
return unless links return unless links
......
...@@ -155,6 +155,14 @@ class Service < ApplicationRecord ...@@ -155,6 +155,14 @@ class Service < ApplicationRecord
end end
end end
def configurable_event_actions
self.class.supported_event_actions
end
def self.supported_event_actions
%w()
end
def supported_events def supported_events
self.class.supported_events self.class.supported_events
end end
......
...@@ -4,14 +4,14 @@ module MergeRequests ...@@ -4,14 +4,14 @@ module MergeRequests
class PushOptionsHandlerService class PushOptionsHandlerService
LIMIT = 10 LIMIT = 10
attr_reader :branches, :changes_by_branch, :current_user, :errors, attr_reader :current_user, :errors, :changes,
:project, :push_options, :target_project :project, :push_options, :target_project
def initialize(project, current_user, changes, push_options) def initialize(project, current_user, changes, push_options)
@project = project @project = project
@target_project = @project.default_merge_request_target @target_project = @project.default_merge_request_target
@current_user = current_user @current_user = current_user
@branches = get_branches(changes) @changes = Gitlab::ChangesList.new(changes)
@push_options = push_options @push_options = push_options
@errors = [] @errors = []
end end
...@@ -34,8 +34,12 @@ module MergeRequests ...@@ -34,8 +34,12 @@ module MergeRequests
private private
def get_branches(raw_changes) def branches
Gitlab::ChangesList.new(raw_changes).map do |changes| changes_by_branch.keys
end
def changes_by_branch
@changes_by_branch ||= changes.each_with_object({}) do |changes, result|
next unless Gitlab::Git.branch_ref?(changes[:ref]) next unless Gitlab::Git.branch_ref?(changes[:ref])
# Deleted branch # Deleted branch
...@@ -45,8 +49,8 @@ module MergeRequests ...@@ -45,8 +49,8 @@ module MergeRequests
branch_name = Gitlab::Git.branch_name(changes[:ref]) branch_name = Gitlab::Git.branch_name(changes[:ref])
next if branch_name == target_project.default_branch next if branch_name == target_project.default_branch
branch_name result[branch_name] = changes
end.compact.uniq end
end end
def validate_service def validate_service
...@@ -101,7 +105,7 @@ module MergeRequests ...@@ -101,7 +105,7 @@ module MergeRequests
project, project,
current_user, current_user,
merge_request.attributes.merge(assignees: merge_request.assignees, merge_request.attributes.merge(assignees: merge_request.assignees,
label_ids: merge_request.label_ids) label_ids: merge_request.label_ids)
).execute ).execute
end end
...@@ -112,7 +116,7 @@ module MergeRequests ...@@ -112,7 +116,7 @@ module MergeRequests
merge_request = ::MergeRequests::UpdateService.new( merge_request = ::MergeRequests::UpdateService.new(
target_project, target_project,
current_user, current_user,
update_params update_params(merge_request)
).execute(merge_request) ).execute(merge_request)
collect_errors_from_merge_request(merge_request) unless merge_request.valid? collect_errors_from_merge_request(merge_request) unless merge_request.valid?
...@@ -130,19 +134,22 @@ module MergeRequests ...@@ -130,19 +134,22 @@ module MergeRequests
params.compact! params.compact!
if push_options.key?(:merge_when_pipeline_succeeds)
params.merge!(
merge_when_pipeline_succeeds: push_options[:merge_when_pipeline_succeeds],
merge_user: current_user
)
end
params[:add_labels] = params.delete(:label).keys if params.has_key?(:label) params[:add_labels] = params.delete(:label).keys if params.has_key?(:label)
params[:remove_labels] = params.delete(:unlabel).keys if params.has_key?(:unlabel) params[:remove_labels] = params.delete(:unlabel).keys if params.has_key?(:unlabel)
params params
end end
def merge_params(branch)
return {} unless push_options.key?(:merge_when_pipeline_succeeds)
{
merge_when_pipeline_succeeds: push_options[:merge_when_pipeline_succeeds],
merge_user: current_user,
sha: changes_by_branch.dig(branch, :newrev)
}
end
def create_params(branch) def create_params(branch)
params = base_params params = base_params
...@@ -153,13 +160,15 @@ module MergeRequests ...@@ -153,13 +160,15 @@ module MergeRequests
target_project: target_project target_project: target_project
) )
params.merge!(merge_params(branch))
params[:target_branch] ||= target_project.default_branch params[:target_branch] ||= target_project.default_branch
params params
end end
def update_params def update_params(merge_request)
base_params base_params.merge(merge_params(merge_request.source_branch))
end end
def collect_errors_from_merge_request(merge_request) def collect_errors_from_merge_request(merge_request)
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
= _("To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here.") = _("To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here.")
.row .row
.form-group.col-sm-12 .form-group.col-sm-12
= hidden_field_tag :namespace_id, @namespace.id
= label_tag :file, _('GitLab project export'), class: 'label-bold' = label_tag :file, _('GitLab project export'), class: 'label-bold'
.form-group .form-group
= file_field_tag :file, class: '' = file_field_tag :file, class: ''
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
- if @service.configurable_events.present? - if @service.configurable_events.present?
.form-group.row .form-group.row
.col-sm-2.text-right Trigger %label.col-form-label.col-sm-2= _('Trigger')
.col-sm-10 .col-sm-10
- @service.configurable_events.each do |event| - @service.configurable_events.each do |event|
...@@ -35,6 +35,22 @@ ...@@ -35,6 +35,22 @@
%p.text-muted %p.text-muted
= @service.class.event_description(event) = @service.class.event_description(event)
- if @service.configurable_event_actions.present?
.form-group.row
%label.col-form-label.col-sm-2= _('Event Actions')
.col-sm-10
- @service.configurable_event_actions.each do |action|
.form-group
.form-check
= form.check_box service_event_action_field_name(action), class: 'form-check-input'
= form.label service_event_action_field_name(action), class: 'form-check-label' do
%strong
= event_action_description(action)
%p.text-muted
= event_action_description(action)
- @service.global_fields.each do |field| - @service.global_fields.each do |field|
- type = field[:type] - type = field[:type]
......
---
title: Add ability to make Jira comments optional
merge_request: 19004
author:
type: added
---
title: Fixed project import from export ignoring namespace selection
merge_request: 20405
author:
type: fixed
---
title: Fix removing of child epics that belong to subgroups
merge_request: 20610
author:
type: fixed
---
title: Fix merging merge requests from push options
merge_request: 20639
author:
type: fixed
---
title: Add 'download' button to Performance Bar
merge_request: 20205
author: Will Chandler
type: changed
# frozen_string_literal: true
class AddCommentActionsToServices < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default(:services, :comment_on_event_enabled, :boolean, default: true)
end
def down
remove_column(:services, :comment_on_event_enabled)
end
end
...@@ -3577,6 +3577,7 @@ ActiveRecord::Schema.define(version: 2019_11_24_150431) do ...@@ -3577,6 +3577,7 @@ ActiveRecord::Schema.define(version: 2019_11_24_150431) do
t.boolean "confidential_note_events", default: true t.boolean "confidential_note_events", default: true
t.boolean "deployment_events", default: false, null: false t.boolean "deployment_events", default: false, null: false
t.string "description", limit: 500 t.string "description", limit: 500
t.boolean "comment_on_event_enabled", default: true, null: false
t.index ["project_id"], name: "index_services_on_project_id" t.index ["project_id"], name: "index_services_on_project_id"
t.index ["template"], name: "index_services_on_template" t.index ["template"], name: "index_services_on_template"
t.index ["type"], name: "index_services_on_type" t.index ["type"], name: "index_services_on_type"
......
...@@ -19,6 +19,7 @@ It allows you to see (from left to right): ...@@ -19,6 +19,7 @@ It allows you to see (from left to right):
- a link to add a request's details to the performance bar; the request can be - a link to add a request's details to the performance bar; the request can be
added by its full URL (authenticated as the current user), or by the value of added by its full URL (authenticated as the current user), or by the value of
its `X-Request-Id` header its `X-Request-Id` header
- a link to download the raw JSON used to generate the Performance Bar reports
On the far right is a request selector that allows you to view the same metrics On the far right is a request selector that allows you to view the same metrics
(excluding the page timing and line profiler) for any requests made while the (excluding the page timing and line profiler) for any requests made while the
......
...@@ -321,6 +321,23 @@ pages: ...@@ -321,6 +321,23 @@ pages:
1. [Reconfigure GitLab][reconfigure] for the changes to take effect. 1. [Reconfigure GitLab][reconfigure] for the changes to take effect.
### Using a custom Certificate Authority (CA) with Access Control
When using certificates issued by a custom CA, Access Control on GitLab Pages may fail to work if the custom CA is not recognized.
This usually results in this error:
`Post /oauth/token: x509: certificate signed by unknown authority`.
For GitLab Pages Access Control with TLS/SSL certs issued by an internal or custom CA:
1. Copy the certificate bundle to `/opt/gitlab/embedded/ssl/certs/` in `.pem` format.
1. [Restart](../restart_gitlab.md) the GitLab Pages Daemon. For GitLab Omnibus instances:
```bash
sudo gitlab-ctl restart gitlab-pages
```
## Activate verbose logging for daemon ## Activate verbose logging for daemon
Verbose logging was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2533) in Verbose logging was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2533) in
......
...@@ -48,8 +48,8 @@ incremental upgrades (and installations) are as simple as possible. ...@@ -48,8 +48,8 @@ incremental upgrades (and installations) are as simple as possible.
review process a new change goes through. review process a new change goes through.
1. Ensuring that tests pass on older release is a considerable challenge in some cases, and as such is very time consuming. 1. Ensuring that tests pass on older release is a considerable challenge in some cases, and as such is very time consuming.
Including new features in patch releases is not possible as that would break [Semantic Versioning]. Including new features in patch releases is not possible as that would break [Semantic Versioning](https://semver.org/).
Breaking [Semantic Versioning] has the following consequences for users that Breaking [Semantic Versioning](https://semver.org/) has the following consequences for users that
have to adhere to various internal requirements (e.g. org. compliance, verifying new features and similar): have to adhere to various internal requirements (e.g. org. compliance, verifying new features and similar):
1. Inability to quickly upgrade to leverage bug fixes included in patch versions. 1. Inability to quickly upgrade to leverage bug fixes included in patch versions.
......
...@@ -63,6 +63,7 @@ Below are the current settings regarding [GitLab CI/CD](../../ci/README.md). ...@@ -63,6 +63,7 @@ Below are the current settings regarding [GitLab CI/CD](../../ci/README.md).
| ----------- | ----------------- | ------------- | | ----------- | ----------------- | ------------- |
| Artifacts maximum size (uncompressed) | 1G | 100M | | Artifacts maximum size (uncompressed) | 1G | 100M |
| Artifacts [expiry time](../../ci/yaml/README.md#artifactsexpire_in) | kept forever | deleted after 30 days unless otherwise specified | | Artifacts [expiry time](../../ci/yaml/README.md#artifactsexpire_in) | kept forever | deleted after 30 days unless otherwise specified |
| Scheduled Pipeline Cron | `*/5 * * * *` | `*/19 * * * *` |
## Repository size limit ## Repository size limit
......
...@@ -34,7 +34,7 @@ namespace. ...@@ -34,7 +34,7 @@ namespace.
This service account will be: This service account will be:
- Added to the installed Helm Tiller - Added to the installed Helm Tiller.
- Used by Helm to install and run [GitLab managed applications](index.md#installing-applications). - Used by Helm to install and run [GitLab managed applications](index.md#installing-applications).
Helm will also create additional service accounts and other resources for each Helm will also create additional service accounts and other resources for each
...@@ -111,6 +111,11 @@ If you don't want to use GitLab Runner in privileged mode, either: ...@@ -111,6 +111,11 @@ If you don't want to use GitLab Runner in privileged mode, either:
## Add new cluster ## Add new cluster
New clusters can be added using GitLab for:
- Google Kubernetes Engine.
- Amazon Elastic Kubernetes Service.
### GKE cluster ### GKE cluster
GitLab supports: GitLab supports:
...@@ -206,43 +211,30 @@ GitLab supports: ...@@ -206,43 +211,30 @@ GitLab supports:
Before creating your first cluster on Amazon EKS with GitLab's integration, Before creating your first cluster on Amazon EKS with GitLab's integration,
make sure the following requirements are met: make sure the following requirements are met:
- Enable the `create_eks_clusters` feature flag for your GitLab instance. - Self-managed GitLab instances have the `create_eks_clusters` feature flag enabled.
- An [Amazon Web Services](https://aws.amazon.com/) account is set up and you are able to log in. - An [Amazon Web Services](https://aws.amazon.com/) account is set up and you are able to log in.
- You have permissions to manage IAM resources. - You have permissions to manage IAM resources.
#### Enable the `create_eks_clusters` feature flag **(CORE ONLY)** ##### Enable the `create_eks_clusters` feature flag **(CORE ONLY)**
NOTE: **Note:**
If you are running a self-managed instance, EKS cluster creation will not be available
unless the feature flag `create_eks_clusters` is enabled. This can be done from the Rails console
by instance administrators.
Use these commands to start the Rails console:
```sh Self-managed instances must have the feature flag `create_eks_clusters` enabled to create
# Omnibus GitLab EKS clusters. To enable EKS cluster creation, ask a GitLab administrator with Rails console access
gitlab-rails console to run the following command:
# Installation from source ```ruby
cd /home/git/gitlab
sudo -u git -H bin/rails console RAILS_ENV=production
```
Then run the following command to enable the feature flag:
```
Feature.enable(:create_eks_clusters) Feature.enable(:create_eks_clusters)
``` ```
You can also enable the feature flag only for specific projects with: To have it enabled for a specific project only, ask a GitLab administrator to run the following
command using a Rails console:
``` ```ruby
Feature.enable(:create_eks_clusters, Project.find_by_full_path('my_group/my_project')) Feature.enable(:create_eks_clusters, Project.find_by_full_path('my_group/my_project'))
``` ```
Run the following command to disable the feature flag: To have this feature disabled, ask a GitLab administrator to run the following command:
``` ```ruby
Feature.disable(:create_eks_clusters) Feature.disable(:create_eks_clusters)
``` ```
......
...@@ -20,7 +20,7 @@ Here's how the integration responds when you take the following actions in GitLa ...@@ -20,7 +20,7 @@ Here's how the integration responds when you take the following actions in GitLa
- **Mention a Jira issue ID** in a commit message or MR (merge request). - **Mention a Jira issue ID** in a commit message or MR (merge request).
- GitLab hyperlinks to the Jira issue. - GitLab hyperlinks to the Jira issue.
- The Jira issue adds an issue link to the commit/MR in GitLab. - The Jira issue adds an issue link to the commit/MR in GitLab.
- The Jira issue adds a comment reflecting the comment made in GitLab, the comment author, and a link to the commit/MR in GitLab. - The Jira issue adds a comment reflecting the comment made in GitLab, the comment author, and a link to the commit/MR in GitLab, unless this commenting to Jira is [disabled](#disabling-comments-on-jira-issues).
- **Mention that a commit or MR 'closes', 'resolves', or 'fixes' a Jira issue ID**. When the commit is made on the project's default branch (usually master) or the change is merged to the default branch: - **Mention that a commit or MR 'closes', 'resolves', or 'fixes' a Jira issue ID**. When the commit is made on the project's default branch (usually master) or the change is merged to the default branch:
- GitLab's merge request page displays a note that it "Closed" the Jira issue, with a link to the issue. (Note: Before the merge, an MR will display that it "Closes" the Jira issue.) - GitLab's merge request page displays a note that it "Closed" the Jira issue, with a link to the issue. (Note: Before the merge, an MR will display that it "Closes" the Jira issue.)
- The Jira issue shows the activity and the Jira issue is closed, or otherwise transitioned. - The Jira issue shows the activity and the Jira issue is closed, or otherwise transitioned.
...@@ -95,6 +95,15 @@ with all Jira projects in your Jira instance and you'll see the Jira link on the ...@@ -95,6 +95,15 @@ with all Jira projects in your Jira instance and you'll see the Jira link on the
![Jira service page](img/jira_service_page_v12_2.png) ![Jira service page](img/jira_service_page_v12_2.png)
### Disabling comments on Jira issues
When you reference a Jira issue, it will always link back to the source commit/MR in GitLab, however, you can control whether GitLab will also cross-post a comment to the Jira issue. That functionality is enabled by default.
To disable the automated commenting on Jira issues:
1. Open the [Integrations page](project_services.md#accessing-the-project-services) and select **Jira**.
1. In the **Event Action** section, uncheck **Comment**.
## Jira issues ## Jira issues
By now you should have [configured Jira](#configuring-jira) and enabled the By now you should have [configured Jira](#configuring-jira) and enabled the
......
...@@ -143,6 +143,7 @@ Changes pushed to the upstream repository will be pulled into the GitLab reposit ...@@ -143,6 +143,7 @@ Changes pushed to the upstream repository will be pulled into the GitLab reposit
CAUTION: **Caution:** CAUTION: **Caution:**
If you do manually update a branch in the GitLab repository, the branch will become diverged from If you do manually update a branch in the GitLab repository, the branch will become diverged from
upstream and GitLab will no longer automatically update this branch to prevent any changes from being lost. upstream and GitLab will no longer automatically update this branch to prevent any changes from being lost.
Also note that deleted branches and tags in the upstream repository will not be reflected in the GitLab repository.
### How it works ### How it works
...@@ -247,6 +248,10 @@ If you need to change the key at any time, you can remove and re-add the mirror ...@@ -247,6 +248,10 @@ If you need to change the key at any time, you can remove and re-add the mirror
to generate a new key. You'll have to update the other repository with the new to generate a new key. You'll have to update the other repository with the new
key to keep the mirror running. key to keep the mirror running.
NOTE: **Note:**
The generated keys are stored in the GitLab database, not in the filesystem. Therefore,
SSH public key authentication for mirrors cannot be used in a pre-receive hook.
### Overwrite diverged branches **(STARTER)** ### Overwrite diverged branches **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. > [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
...@@ -362,6 +367,7 @@ proxy_push() ...@@ -362,6 +367,7 @@ proxy_push()
branch=$(expr "$refname" : "refs/heads/\(.*\)") branch=$(expr "$refname" : "refs/heads/\(.*\)")
if [ "$whitelisted" = "$branch" ]; then if [ "$whitelisted" = "$branch" ]; then
unset GIT_QUARANTINE_PATH # handle https://git-scm.com/docs/git-receive-pack#_quarantine_environment
error="$(git push --quiet $TARGET_REPO $NEWREV:$REFNAME 2>&1)" error="$(git push --quiet $TARGET_REPO $NEWREV:$REFNAME 2>&1)"
fail=$? fail=$?
...@@ -396,6 +402,15 @@ else ...@@ -396,6 +402,15 @@ else
fi fi
``` ```
Note that this sample has a few limitations:
- This example may not work verbatim for your use case and might need modification.
- It does not regard different types of authentication mechanisms for the mirror.
- It does not work with forced updates (rewriting history).
- Only branches that match the `whitelisted` patterns will be proxy pushed.
- The script circumvents the git hook quarantine environment because the update of `$TARGET_REPO`
is seen as a ref update and git will complain about it.
### Mirroring with Perforce Helix via Git Fusion **(STARTER)** ### Mirroring with Perforce Helix via Git Fusion **(STARTER)**
CAUTION: **Warning:** CAUTION: **Warning:**
......
...@@ -486,6 +486,12 @@ module API ...@@ -486,6 +486,12 @@ module API
name: :jira_issue_transition_id, name: :jira_issue_transition_id,
type: String, type: String,
desc: 'The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`' desc: 'The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`'
},
{
required: false,
name: :comment_on_event_enabled,
type: Boolean,
desc: 'Enable comments inside Jira issues on each GitLab event (commit / merge request)'
} }
], ],
'mattermost-slash-commands' => [ 'mattermost-slash-commands' => [
......
...@@ -5783,9 +5783,15 @@ msgstr "" ...@@ -5783,9 +5783,15 @@ msgstr ""
msgid "Deselect all" msgid "Deselect all"
msgstr "" msgstr ""
msgid "Design Management"
msgstr ""
msgid "Design Management files and data" msgid "Design Management files and data"
msgstr "" msgstr ""
msgid "Design Sync Not Enabled"
msgstr ""
msgid "DesignManagement|%{current_design} of %{designs_count}" msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "" msgstr ""
...@@ -5855,6 +5861,9 @@ msgstr "" ...@@ -5855,6 +5861,9 @@ msgstr ""
msgid "Designs" msgid "Designs"
msgstr "" msgstr ""
msgid "Designs coming soon."
msgstr ""
msgid "Destroy" msgid "Destroy"
msgstr "" msgstr ""
...@@ -6929,6 +6938,9 @@ msgstr "" ...@@ -6929,6 +6938,9 @@ msgstr ""
msgid "Estimated" msgid "Estimated"
msgstr "" msgstr ""
msgid "Event Actions"
msgstr ""
msgid "EventFilterBy|Filter by all" msgid "EventFilterBy|Filter by all"
msgstr "" msgstr ""
...@@ -7807,12 +7819,18 @@ msgstr "" ...@@ -7807,12 +7819,18 @@ msgstr ""
msgid "Geo" msgid "Geo"
msgstr "" msgstr ""
msgid "Geo Designs"
msgstr ""
msgid "Geo Nodes" msgid "Geo Nodes"
msgstr "" msgstr ""
msgid "Geo Settings" msgid "Geo Settings"
msgstr "" msgstr ""
msgid "Geo Troubleshooting"
msgstr ""
msgid "Geo allows you to replicate your GitLab instance to other geographical locations." msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
msgstr "" msgstr ""
...@@ -9225,6 +9243,9 @@ msgstr "" ...@@ -9225,6 +9243,9 @@ msgstr ""
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}" msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "" msgstr ""
msgid "If you believe this page to be an error, check out the links below for more information."
msgstr ""
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes." msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr "" msgstr ""
...@@ -12224,6 +12245,9 @@ msgstr "" ...@@ -12224,6 +12245,9 @@ msgstr ""
msgid "Performance optimization" msgid "Performance optimization"
msgstr "" msgstr ""
msgid "PerformanceBar|Download"
msgstr ""
msgid "PerformanceBar|Gitaly calls" msgid "PerformanceBar|Gitaly calls"
msgstr "" msgstr ""
...@@ -13367,6 +13391,12 @@ msgstr "" ...@@ -13367,6 +13391,12 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on" msgid "ProjectService|%{service_title}: status on"
msgstr "" msgstr ""
msgid "ProjectService|Comment"
msgstr ""
msgid "ProjectService|Comment will be posted on each event"
msgstr ""
msgid "ProjectService|Integrations" msgid "ProjectService|Integrations"
msgstr "" msgstr ""
...@@ -17549,6 +17579,9 @@ msgstr "" ...@@ -17549,6 +17579,9 @@ msgstr ""
msgid "There was an error fetching label data for the selected group" msgid "There was an error fetching label data for the selected group"
msgstr "" msgstr ""
msgid "There was an error fetching the Designs"
msgstr ""
msgid "There was an error gathering the chart data" msgid "There was an error gathering the chart data"
msgstr "" msgstr ""
...@@ -18429,6 +18462,9 @@ msgstr "" ...@@ -18429,6 +18462,9 @@ msgstr ""
msgid "Trending" msgid "Trending"
msgstr "" msgstr ""
msgid "Trigger"
msgstr ""
msgid "Trigger pipelines for mirror updates" msgid "Trigger pipelines for mirror updates"
msgstr "" msgstr ""
......
...@@ -4,23 +4,9 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -4,23 +4,9 @@ import { shallowMount } from '@vue/test-utils';
describe('request selector', () => { describe('request selector', () => {
const requests = [ const requests = [
{ {
id: '123', id: 'warningReq',
url: 'https://gitlab.com/',
hasWarnings: false,
},
{
id: '456',
url: 'https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1',
hasWarnings: false,
},
{
id: '789',
url: 'https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1.json?serializer=widget',
hasWarnings: false,
},
{
id: 'abc',
url: 'https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1/discussions.json', url: 'https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1/discussions.json',
truncatedUrl: 'discussions.json',
hasWarnings: true, hasWarnings: true,
}, },
]; ];
...@@ -28,35 +14,16 @@ describe('request selector', () => { ...@@ -28,35 +14,16 @@ describe('request selector', () => {
const wrapper = shallowMount(RequestSelector, { const wrapper = shallowMount(RequestSelector, {
propsData: { propsData: {
requests, requests,
currentRequest: requests[1], currentRequest: requests[0],
}, },
}); });
function optionText(requestId) {
return wrapper
.find(`[value='${requestId}']`)
.text()
.trim();
}
it('displays the last component of the path', () => {
expect(optionText(requests[2].id)).toEqual('1.json?serializer=widget');
});
it('keeps the last two components of the path when the last component is numeric', () => {
expect(optionText(requests[1].id)).toEqual('merge_requests/1');
});
it('ignores trailing slashes', () => {
expect(optionText(requests[0].id)).toEqual('gitlab.com');
});
it('has a warning icon if any requests have warnings', () => { it('has a warning icon if any requests have warnings', () => {
expect(wrapper.find('span > gl-emoji').element.dataset.name).toEqual('warning'); expect(wrapper.find('span > gl-emoji').element.dataset.name).toEqual('warning');
}); });
it('adds a warning glyph to requests with warnings', () => { it('adds a warning glyph to requests with warnings', () => {
const requestValue = wrapper.find('[value="abc"]').text(); const requestValue = wrapper.find('[value="warningReq"]').text();
expect(requestValue).toContain('discussions.json'); expect(requestValue).toContain('discussions.json');
expect(requestValue).toContain('(!)'); expect(requestValue).toContain('(!)');
......
import PerformanceBarStore from '~/performance_bar/stores/performance_bar_store';
describe('PerformanceBarStore', () => {
describe('truncateUrl', () => {
let store;
const findUrl = id => store.findRequest(id).truncatedUrl;
beforeEach(() => {
store = new PerformanceBarStore();
});
it('ignores trailing slashes', () => {
store.addRequest('id', 'https://gitlab.com/');
expect(findUrl('id')).toEqual('gitlab.com');
});
it('keeps the last two components of the path when the last component is numeric', () => {
store.addRequest('id', 'https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1');
expect(findUrl('id')).toEqual('merge_requests/1');
});
it('uses the last component of the path', () => {
store.addRequest(
'id',
'https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/1.json?serializer=widget',
);
expect(findUrl('id')).toEqual('1.json?serializer=widget');
});
it('keeps query components', () => {
store.addRequest('id', 'http://localhost:3001/h5bp/html5-boilerplate/?param');
expect(findUrl('id')).toEqual('html5-boilerplate?param');
});
it('keeps components when query contains a slash', () => {
store.addRequest('id', 'http://localhost:3001/h5bp/html5-boilerplate?trunc/ated');
expect(findUrl('id')).toEqual('html5-boilerplate?trunc/ated');
});
it('ignores fragments', () => {
store.addRequest('id', 'http://localhost:3001/h5bp/html5-boilerplate/#frag/ment');
expect(findUrl('id')).toEqual('html5-boilerplate');
});
});
});
# frozen_string_literal: true
require 'spec_helper'
describe ServicesHelper do
describe 'event_action_title' do
it { expect(event_action_title('comment')).to eq 'Comment' }
it { expect(event_action_title('something')).to eq 'Something' }
end
describe 'event_action_description' do
it { expect(event_action_description('comment')).to eq 'Comment will be posted on each event' }
it { expect(event_action_description('something')).to eq nil }
end
end
...@@ -171,7 +171,10 @@ describe('test errors', () => { ...@@ -171,7 +171,10 @@ describe('test errors', () => {
// see: https://github.com/deepsweet/istanbul-instrumenter-loader/issues/15 // see: https://github.com/deepsweet/istanbul-instrumenter-loader/issues/15
if (process.env.BABEL_ENV === 'coverage') { if (process.env.BABEL_ENV === 'coverage') {
// exempt these files from the coverage report // exempt these files from the coverage report
const troubleMakers = ['./pages/admin/application_settings/general/index.js']; const troubleMakers = [
'./pages/admin/application_settings/general/index.js',
'./geo_designs/index.js',
];
describe('Uncovered files', function() { describe('Uncovered files', function() {
const sourceFilesContexts = [require.context('~', true, /\.(js|vue)$/)]; const sourceFilesContexts = [require.context('~', true, /\.(js|vue)$/)];
......
...@@ -443,6 +443,7 @@ Service: ...@@ -443,6 +443,7 @@ Service:
- note_events - note_events
- pipeline_events - pipeline_events
- job_events - job_events
- comment_on_event_enabled
- category - category
- default - default
- wiki_page_events - wiki_page_events
......
...@@ -431,6 +431,16 @@ describe JiraService do ...@@ -431,6 +431,16 @@ describe JiraService do
).once ).once
end end
context 'when "comment_on_event_enabled" is set to false' do
it 'creates Remote Link reference but does not create comment' do
allow(@jira_service).to receive_messages(comment_on_event_enabled: false)
@jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
expect(WebMock).not_to have_requested(:post, @comment_url)
expect(WebMock).to have_requested(:post, @remote_link_url)
end
end
it 'does not send comment or remote links to issues already closed' do it 'does not send comment or remote links to issues already closed' do
allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(true) allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(true)
......
...@@ -101,17 +101,15 @@ describe MergeRequests::PushOptionsHandlerService do ...@@ -101,17 +101,15 @@ describe MergeRequests::PushOptionsHandlerService do
shared_examples_for 'a service that can set the merge request to merge when pipeline succeeds' do shared_examples_for 'a service that can set the merge request to merge when pipeline succeeds' do
subject(:last_mr) { MergeRequest.last } subject(:last_mr) { MergeRequest.last }
let(:change) { Gitlab::ChangesList.new(changes).changes.first }
it 'sets auto_merge_enabled' do it 'sets auto_merge_enabled' do
service.execute service.execute
expect(last_mr.auto_merge_enabled).to eq(true) expect(last_mr.auto_merge_enabled).to eq(true)
expect(last_mr.auto_merge_strategy).to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS) expect(last_mr.auto_merge_strategy).to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
end
it 'sets merge_user to the user' do
service.execute
expect(last_mr.merge_user).to eq(user) expect(last_mr.merge_user).to eq(user)
expect(last_mr.merge_params['sha']).to eq(change[:newrev])
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
describe 'import/gitlab_projects/new.html.haml' do
include Devise::Test::ControllerHelpers
let(:user) { build_stubbed(:user, namespace: build_stubbed(:namespace)) }
before do
allow(view).to receive(:current_user).and_return(user)
end
context 'when the user has no other namespaces' do
it 'shows a namespace_id hidden field tag' do
render
expect(rendered).to have_css('input[name="namespace_id"]', count: 1, visible: false)
end
end
context 'when the user can select other namespaces' do
it 'shows a namespace_id select' do
allow(user).to receive(:can_select_namespace?).and_return(true)
render
expect(rendered).to have_select('namespace_id', count: 1)
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment