Commit b570d73e authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 34b3567c
...@@ -188,6 +188,7 @@ module ProjectsHelper ...@@ -188,6 +188,7 @@ module ProjectsHelper
"cross-project:#{can?(current_user, :read_cross_project)}", "cross-project:#{can?(current_user, :read_cross_project)}",
max_project_member_access_cache_key(project), max_project_member_access_cache_key(project),
pipeline_status, pipeline_status,
Gitlab::I18n.locale,
'v2.6' 'v2.6'
] ]
......
...@@ -599,12 +599,6 @@ module Ci ...@@ -599,12 +599,6 @@ module Ci
project.notes.for_commit_id(sha) project.notes.for_commit_id(sha)
end end
# rubocop: disable CodeReuse/ServiceClass
def process!(trigger_build_ids = nil)
Ci::ProcessPipelineService.new(project, user).execute(self, trigger_build_ids)
end
# rubocop: enable CodeReuse/ServiceClass
def update_status def update_status
retry_optimistic_lock(self) do retry_optimistic_lock(self) do
new_status = latest_builds_status.to_s new_status = latest_builds_status.to_s
......
...@@ -23,7 +23,6 @@ module Issuable ...@@ -23,7 +23,6 @@ module Issuable
include Sortable include Sortable
include CreatedAtFilterable include CreatedAtFilterable
include UpdatedAtFilterable include UpdatedAtFilterable
include IssuableStates
include ClosedAtFilterable include ClosedAtFilterable
include VersionedDescription include VersionedDescription
......
# frozen_string_literal: true
module IssuableStates
extend ActiveSupport::Concern
# The state:string column is being migrated to state_id:integer column
# This is a temporary hook to keep state column in sync until it is removed.
# Check https: https://gitlab.com/gitlab-org/gitlab/issues/33814 for more information
# The state column can be safely removed after 2019-10-27
included do
before_save :sync_issuable_deprecated_state
end
def sync_issuable_deprecated_state
return if self.is_a?(Epic)
return unless respond_to?(:state)
return if state_id.nil?
deprecated_state = self.class.available_states.key(state_id)
self.write_attribute(:state, deprecated_state)
end
end
...@@ -66,7 +66,10 @@ class Issue < ApplicationRecord ...@@ -66,7 +66,10 @@ class Issue < ApplicationRecord
scope :public_only, -> { where(confidential: false) } scope :public_only, -> { where(confidential: false) }
scope :confidential_only, -> { where(confidential: true) } scope :confidential_only, -> { where(confidential: true) }
scope :counts_by_state, -> { reorder(nil).group(:state).count } scope :counts_by_state, -> { reorder(nil).group(:state_id).count }
# Only remove after 2019-12-22 and with %12.7
self.ignored_columns += %i[state]
after_commit :expire_etag_cache after_commit :expire_etag_cache
after_save :ensure_metrics, unless: :imported? after_save :ensure_metrics, unless: :imported?
......
...@@ -228,6 +228,9 @@ class MergeRequest < ApplicationRecord ...@@ -228,6 +228,9 @@ class MergeRequest < ApplicationRecord
with_state(:opened).where(auto_merge_enabled: true) with_state(:opened).where(auto_merge_enabled: true)
end end
# Only remove after 2019-12-22 and with %12.7
self.ignored_columns += %i[state]
after_save :keep_around_commit after_save :keep_around_commit
alias_attribute :project, :target_project alias_attribute :project, :target_project
......
...@@ -58,6 +58,7 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated ...@@ -58,6 +58,7 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
end end
def release_edit_page_available? def release_edit_page_available?
::Feature.enabled?(:release_edit_page, project, default_enabled: true) ::Feature.enabled?(:release_edit_page, project, default_enabled: true) &&
can?(current_user, :update_release, release)
end end
end end
# frozen_string_literal: true # frozen_string_literal: true
class AnalyticsMergeRequestEntity < AnalyticsIssueEntity class AnalyticsMergeRequestEntity < AnalyticsIssueEntity
expose :state expose :state do |object|
MergeRequest.available_states.key(object[:state_id])
end
expose :url do |object| expose :url do |object|
url_to(:namespace_project_merge_request, object) url_to(:namespace_project_merge_request, object)
......
...@@ -57,7 +57,9 @@ module Ci ...@@ -57,7 +57,9 @@ module Ci
cancel_pending_pipelines if project.auto_cancel_pending_pipelines? cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
pipeline_created_counter.increment(source: source) pipeline_created_counter.increment(source: source)
pipeline.process! Ci::ProcessPipelineService
.new(pipeline)
.execute
end end
end end
......
# frozen_string_literal: true # frozen_string_literal: true
module Ci module Ci
class ProcessPipelineService < BaseService class ProcessPipelineService
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
attr_reader :pipeline attr_reader :pipeline
def execute(pipeline, trigger_build_ids = nil) def initialize(pipeline)
@pipeline = pipeline @pipeline = pipeline
end
def execute(trigger_build_ids = nil)
update_retried update_retried
success = process_stages_without_needs success = process_stages_without_needs
...@@ -72,7 +74,7 @@ module Ci ...@@ -72,7 +74,7 @@ module Ci
def process_build(build, current_status) def process_build(build, current_status)
Gitlab::OptimisticLocking.retry_lock(build) do |subject| Gitlab::OptimisticLocking.retry_lock(build) do |subject|
Ci::ProcessBuildService.new(project, @user) Ci::ProcessBuildService.new(project, build.user)
.execute(subject, current_status) .execute(subject, current_status)
end end
end end
...@@ -129,5 +131,9 @@ module Ci ...@@ -129,5 +131,9 @@ module Ci
.update_all(retried: true) if latest_statuses.any? .update_all(retried: true) if latest_statuses.any?
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
def project
pipeline.project
end
end end
end end
...@@ -24,7 +24,9 @@ module Ci ...@@ -24,7 +24,9 @@ module Ci
.new(project, current_user) .new(project, current_user)
.close_all(pipeline) .close_all(pipeline)
pipeline.process! Ci::ProcessPipelineService
.new(pipeline)
.execute
end end
end end
end end
...@@ -397,7 +397,7 @@ class IssuableBaseService < BaseService ...@@ -397,7 +397,7 @@ class IssuableBaseService < BaseService
end end
def update_project_counter_caches?(issuable) def update_project_counter_caches?(issuable)
issuable.state_changed? issuable.state_id_changed?
end end
def parent def parent
......
...@@ -11,7 +11,9 @@ class PipelineProcessWorker ...@@ -11,7 +11,9 @@ class PipelineProcessWorker
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id, build_ids = nil) def perform(pipeline_id, build_ids = nil)
Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline| Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
pipeline.process!(build_ids) Ci::ProcessPipelineService
.new(pipeline)
.execute(build_ids)
end end
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
......
---
title: Creates DB tables for storing mentioned users, groups, projects referenced
in a note or issuable description
merge_request: 18316
author:
type: added
---
title: Add link color to design comments
merge_request: 20302
author:
type: fixed
---
title: Remove Release edit url for users not allowed to update a release
merge_request: 20136
author:
type: fixed
---
title: Fix projects list to show info in user's locale
merge_request: 20015
author: Arun Kumar Mohan
type: fixed
...@@ -93,7 +93,7 @@ tables: ...@@ -93,7 +93,7 @@ tables:
- updated_at - updated_at
- description - description
- milestone_id - milestone_id
- state - state_id
- updated_by_id - updated_by_id
- weight - weight
- due_date - due_date
...@@ -174,7 +174,7 @@ tables: ...@@ -174,7 +174,7 @@ tables:
- created_at - created_at
- updated_at - updated_at
- milestone_id - milestone_id
- state - state_id
- merge_status - merge_status
- target_project_id - target_project_id
- updated_by_id - updated_by_id
......
# frozen_string_literal: true
class CreateIssueUserMentions < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :issue_user_mentions do |t|
t.references :issue, type: :integer, index: false, null: false, foreign_key: { on_delete: :cascade }
t.references :note, type: :integer,
index: { where: 'note_id IS NOT NULL', unique: true }, null: true, foreign_key: { on_delete: :cascade }
t.integer :mentioned_users_ids, array: true
t.integer :mentioned_projects_ids, array: true
t.integer :mentioned_groups_ids, array: true
end
add_index :issue_user_mentions, [:issue_id], where: 'note_id is null', unique: true, name: 'issue_user_mentions_on_issue_id_index'
add_index :issue_user_mentions, [:issue_id, :note_id], unique: true, name: 'issue_user_mentions_on_issue_id_and_note_id_index'
end
end
# frozen_string_literal: true
class CreateMergeRequestUserMentions < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :merge_request_user_mentions do |t|
t.references :merge_request, type: :integer, index: false, null: false, foreign_key: { on_delete: :cascade }
t.references :note, type: :integer,
index: { where: 'note_id IS NOT NULL', unique: true }, null: true, foreign_key: { on_delete: :cascade }
t.integer :mentioned_users_ids, array: true
t.integer :mentioned_projects_ids, array: true
t.integer :mentioned_groups_ids, array: true
end
add_index :merge_request_user_mentions, [:merge_request_id], where: 'note_id is null', unique: true, name: 'merge_request_user_mentions_on_mr_id_index'
add_index :merge_request_user_mentions, [:merge_request_id, :note_id], unique: true, name: 'merge_request_user_mentions_on_mr_id_and_note_id_index'
end
end
# frozen_string_literal: true
class CreateEpicUserMentions < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :epic_user_mentions do |t|
t.references :epic, type: :integer, index: false, null: false, foreign_key: { on_delete: :cascade }
t.references :note, type: :integer,
index: { where: 'note_id IS NOT NULL', unique: true }, null: true, foreign_key: { on_delete: :cascade }
t.integer :mentioned_users_ids, array: true
t.integer :mentioned_projects_ids, array: true
t.integer :mentioned_groups_ids, array: true
end
add_index :epic_user_mentions, [:epic_id], where: 'note_id is null', unique: true, name: 'epic_user_mentions_on_epic_id_index'
add_index :epic_user_mentions, [:epic_id, :note_id], unique: true, name: 'epic_user_mentions_on_epic_id_and_note_id_index'
end
end
# frozen_string_literal: true
class CreateCommitUserMentions < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :commit_user_mentions do |t|
t.references :note, type: :integer,
index: { unique: true }, null: false, foreign_key: { on_delete: :cascade }
t.binary :commit_id, null: false
t.integer :mentioned_users_ids, array: true
t.integer :mentioned_projects_ids, array: true
t.integer :mentioned_groups_ids, array: true
end
add_index :commit_user_mentions, [:commit_id, :note_id], name: 'commit_user_mentions_on_commit_id_and_note_id_index'
end
end
# frozen_string_literal: true
class CreateSnippetUserMentions < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :snippet_user_mentions do |t|
t.references :snippet, type: :integer, index: false, null: false, foreign_key: { on_delete: :cascade }
t.references :note, type: :integer,
index: { where: 'note_id IS NOT NULL', unique: true }, null: true, foreign_key: { on_delete: :cascade }
t.integer :mentioned_users_ids, array: true
t.integer :mentioned_projects_ids, array: true
t.integer :mentioned_groups_ids, array: true
end
add_index :snippet_user_mentions, [:snippet_id], where: 'note_id is null', unique: true, name: 'snippet_user_mentions_on_snippet_id_index'
add_index :snippet_user_mentions, [:snippet_id, :note_id], unique: true, name: 'snippet_user_mentions_on_snippet_id_and_note_id_index'
end
end
# frozen_string_literal: true
class CreateDesignUserMentions < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :design_user_mentions do |t|
t.references :design, type: :integer, index: false, null: false,
foreign_key: { to_table: :design_management_designs, column: :design_id, on_delete: :cascade }
t.references :note, type: :integer,
index: { unique: true }, null: false, foreign_key: { on_delete: :cascade }
t.integer :mentioned_users_ids, array: true
t.integer :mentioned_projects_ids, array: true
t.integer :mentioned_groups_ids, array: true
end
add_index :design_user_mentions, [:design_id, :note_id], name: 'design_user_mentions_on_design_id_and_note_id_index'
end
end
# frozen_string_literal: true
class CreateServiceDeskSettings < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :service_desk_settings, id: false do |t|
t.references :project,
primary_key: true,
default: nil,
null: false,
index: false,
foreign_key: { on_delete: :cascade }
t.string :issue_template_key, limit: 255
end
end
end
# frozen_string_literal: true
class NullifyUsersRole < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
INDEX_NAME = 'partial_index_users_updated_at_for_cleaning_mistaken_values'.freeze
DOWNTIME = false
def up
# expected updated users count is around 10K
# rubocop: disable Migration/UpdateLargeTable
add_concurrent_index(:users, :updated_at, where: 'role = 0', name: INDEX_NAME)
update_column_in_batches(:users, :role, nil) do |table, query|
query.where(table[:updated_at].lt('2019-11-05 12:08:00')).where(table[:role].eq(0))
end
remove_concurrent_index_by_name(:users, INDEX_NAME)
end
def down
# noop
end
end
This diff is collapsed.
...@@ -49,6 +49,22 @@ purposes. ...@@ -49,6 +49,22 @@ purposes.
In this setup guide we will start by configuring Praefect, then its child In this setup guide we will start by configuring Praefect, then its child
Gitaly nodes, and lastly the GitLab server configuration. Gitaly nodes, and lastly the GitLab server configuration.
#### Secrets
We need to manage the following secrets and make them match across hosts:
1. `GITLAB_SHELL_SECRET_TOKEN`: this is used by Git hooks to make
callback HTTP API requests to GitLab when accepting a Git push. This
secret is shared with GitLab Shell for legacy reasons.
1. `PRAEFECT_EXTERNAL_TOKEN`: repositories hosted on your Praefect
cluster can only be accessed by Gitaly clients that carry this
token.
1. `PRAEFECT_INTERNAL_TOKEN`: this token is used for replication
traffic inside your Praefect cluster. This is distinct from
`PRAEFECT_EXTERNAL_TOKEN` because Gitaly clients must not be able to
access internal nodes of the Praefect cluster directly; that could
lead to data loss.
#### Praefect #### Praefect
On the Praefect node we disable all other services, including Gitaly. We list each On the Praefect node we disable all other services, including Gitaly. We list each
...@@ -57,14 +73,8 @@ Gitaly node that will be connected to Praefect under `praefect['storage_nodes']` ...@@ -57,14 +73,8 @@ Gitaly node that will be connected to Praefect under `praefect['storage_nodes']`
In the example below, the Gitaly nodes are named `praefect-gitaly-N`. Note that one In the example below, the Gitaly nodes are named `praefect-gitaly-N`. Note that one
node is designated as primary by setting the primary to `true`. node is designated as primary by setting the primary to `true`.
`praefect['auth_token']` is the token used to authenticate with the GitLab server,
just like `gitaly['auth_token']` is used for a standard Gitaly server.
The `token` field under each storage listed in `praefect['storage_nodes']` is used
to authenticate each child Gitaly node with Praefect.
```ruby ```ruby
# /etc/gitlab/gitlab.rb # /etc/gitlab/gitlab.rb on praefect server
# Avoid running unnecessary services on the Gitaly server # Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false postgresql['enable'] = false
...@@ -83,7 +93,7 @@ In the example below, the Gitaly nodes are named `praefect-git-X`. Note that one ...@@ -83,7 +93,7 @@ In the example below, the Gitaly nodes are named `praefect-git-X`. Note that one
primary, by setting the primary to `true`: primary, by setting the primary to `true`:
```ruby ```ruby
# /etc/gitlab/gitlab.rb # /etc/gitlab/gitlab.rb on praefect server
# Prevent database connections during 'gitlab-ctl reconfigure' # Prevent database connections during 'gitlab-ctl reconfigure'
gitlab_rails['rake_cache_clear'] = false gitlab_rails['rake_cache_clear'] = false
...@@ -98,22 +108,24 @@ praefect['listen_addr'] = '0.0.0.0:2305' ...@@ -98,22 +108,24 @@ praefect['listen_addr'] = '0.0.0.0:2305'
# virtual_storage_name must match the same storage name given to praefect in git_data_dirs # virtual_storage_name must match the same storage name given to praefect in git_data_dirs
praefect['virtual_storage_name'] = 'praefect' praefect['virtual_storage_name'] = 'praefect'
# Authentication token to ensure only authorized servers can communicate with # Replace PRAEFECT_EXTERNAL_TOKEN with a real secret
# Praefect server praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN'
praefect['auth_token'] = 'praefect-token'
# Replace each instance of PRAEFECT_INTERNAL_TOKEN below with a real
# secret, distinct from PRAEFECT_EXTERNAL_TOKEN.
praefect['storage_nodes'] = { praefect['storage_nodes'] = {
'praefect-gitaly-1' => { 'praefect-gitaly-1' => {
'address' => 'tcp://praefect-git-1.internal:8075', 'address' => 'tcp://praefect-git-1.internal:8075',
'token' => 'praefect-gitaly-token', 'token' => 'PRAEFECT_INTERNAL_TOKEN',
'primary' => true 'primary' => true
}, },
'praefect-gitaly-2' => { 'praefect-gitaly-2' => {
'address' => 'tcp://praefect-git-2.internal:8075', 'address' => 'tcp://praefect-git-2.internal:8075',
'token' => 'praefect-gitaly-token' 'token' => 'PRAEFECT_INTERNAL_TOKEN'
}, },
'praefect-gitaly-3' => { 'praefect-gitaly-3' => {
'address' => 'tcp://praefect-git-3.internal:8075', 'address' => 'tcp://praefect-git-3.internal:8075',
'token' => 'praefect-gitaly-token' 'token' => 'PRAEFECT_INTERNAL_TOKEN'
} }
} }
``` ```
...@@ -133,7 +145,7 @@ Note that `gitaly['auth_token']` matches the `token` value listed under `praefec ...@@ -133,7 +145,7 @@ Note that `gitaly['auth_token']` matches the `token` value listed under `praefec
on the Praefect node. on the Praefect node.
```ruby ```ruby
# /etc/gitlab/gitlab.rb # /etc/gitlab/gitlab.rb on gitaly node inside praefect cluster
# Avoid running unnecessary services on the Gitaly server # Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false postgresql['enable'] = false
...@@ -148,15 +160,16 @@ gitlab_workhorse['enable'] = false ...@@ -148,15 +160,16 @@ gitlab_workhorse['enable'] = false
gitlab_rails['rake_cache_clear'] = false gitlab_rails['rake_cache_clear'] = false
gitlab_rails['auto_migrate'] = false gitlab_rails['auto_migrate'] = false
# Replace GITLAB_SHELL_SECRET_TOKEN below with real secret
gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
# Configure the gitlab-shell API callback URL. Without this, `git push` will # Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load # fail. This can be your 'front door' GitLab URL or an internal load
# balancer. # balancer.
# Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
# Authentication token to ensure only authorized servers can communicate with # Replace PRAEFECT_INTERNAL_TOKEN below with a real secret.
# Gitaly server gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN'
gitaly['auth_token'] = 'praefect-gitaly-token'
# Make Gitaly accept connections on all network interfaces. You must use # Make Gitaly accept connections on all network interfaces. You must use
# firewalls to restrict access to this address/port. # firewalls to restrict access to this address/port.
...@@ -170,9 +183,6 @@ git_data_dirs({ ...@@ -170,9 +183,6 @@ git_data_dirs({
}) })
``` ```
Note that just as with a standard Gitaly server, `/etc/gitlab/gitlab-secrets.json` must
be copied from the GitLab server to the Gitaly node for authentication purposes.
For more information on Gitaly server configuration, see our [gitaly documentation](index.md#3-gitaly-server-configuration). For more information on Gitaly server configuration, see our [gitaly documentation](index.md#3-gitaly-server-configuration).
#### GitLab #### GitLab
...@@ -182,24 +192,26 @@ is done through setting the `git_data_dirs`. Assuming the default storage ...@@ -182,24 +192,26 @@ is done through setting the `git_data_dirs`. Assuming the default storage
is present, there should be two storages available to GitLab: is present, there should be two storages available to GitLab:
```ruby ```ruby
# /etc/gitlab/gitlab.rb on gitlab server
# Replace PRAEFECT_EXTERNAL_TOKEN below with real secret.
git_data_dirs({ git_data_dirs({
"default" => { "default" => {
"gitaly_address" => "tcp://gitaly.internal" "gitaly_address" => "tcp://gitaly.internal"
}, },
"praefect" => { "praefect" => {
"gitaly_address" => "tcp://praefect.internal:2305" "gitaly_address" => "tcp://praefect.internal:2305",
"gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
} }
}) })
gitlab_rails['gitaly_token'] = 'praefect-token' # Replace GITLAB_SHELL_SECRET_TOKEN below with real secret
gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
``` ```
Note that the storage name used is the same as the `praefect['virtual_storage_name']` set Note that the storage name used is the same as the `praefect['virtual_storage_name']` set
on the Praefect node. on the Praefect node.
Also, the `gitlab_rails['gitaly_token']` matches the value of `praefect['auth_token']`
on Praefect.
Restart GitLab using `gitlab-ctl restart` on the GitLab node. Restart GitLab using `gitlab-ctl restart` on the GitLab node.
### Testing Praefect ### Testing Praefect
...@@ -211,7 +223,3 @@ create a new project and check the "Initialize repository with a README" box. ...@@ -211,7 +223,3 @@ create a new project and check the "Initialize repository with a README" box.
If you receive a 503 error, check `/var/log/gitlab/gitlab-rails/production.log`. If you receive a 503 error, check `/var/log/gitlab/gitlab-rails/production.log`.
A `GRPC::Unavailable (14:failed to connect to all addresses)` error indicates A `GRPC::Unavailable (14:failed to connect to all addresses)` error indicates
that GitLab was unable to connect to Praefect. that GitLab was unable to connect to Praefect.
If the project is created but the README is not, then ensure that the
`/etc/gitlab/gitlab-secrets.json` file from the GitLab server has been copied
to the Gitaly servers.
...@@ -15,7 +15,7 @@ SAST supports the following official analyzers: ...@@ -15,7 +15,7 @@ SAST supports the following official analyzers:
- [`bandit`](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) (Bandit) - [`bandit`](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) (Bandit)
- [`brakeman`](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman) (Brakeman) - [`brakeman`](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman) (Brakeman)
- [`eslint`](https://gitlab.com/gitlab-org/security-products/analyzers/eslint) (ESLint (JavaScript)) - [`eslint`](https://gitlab.com/gitlab-org/security-products/analyzers/eslint) (ESLint (JavaScript and React))
- [`flawfinder`](https://gitlab.com/gitlab-org/security-products/analyzers/flawfinder) (Flawfinder) - [`flawfinder`](https://gitlab.com/gitlab-org/security-products/analyzers/flawfinder) (Flawfinder)
- [`gosec`](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) (Gosec) - [`gosec`](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) (Gosec)
- [`nodejs-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan) (NodeJsScan) - [`nodejs-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan) (NodeJsScan)
......
...@@ -76,6 +76,7 @@ The following table shows which languages, package managers and frameworks are s ...@@ -76,6 +76,7 @@ The following table shows which languages, package managers and frameworks are s
| Node.js | [NodeJsScan](https://github.com/ajinabraham/NodeJsScan) | 11.1 | | Node.js | [NodeJsScan](https://github.com/ajinabraham/NodeJsScan) | 11.1 |
| PHP | [phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit) | 10.8 | | PHP | [phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit) | 10.8 |
| Python ([pip](https://pip.pypa.io/en/stable/)) | [bandit](https://github.com/PyCQA/bandit) | 10.3 | | Python ([pip](https://pip.pypa.io/en/stable/)) | [bandit](https://github.com/PyCQA/bandit) | 10.3 |
| React | [ESLint react plugin](https://github.com/yannickcr/eslint-plugin-react) | 12.5 |
| Ruby on Rails | [brakeman](https://brakemanscanner.org) | 10.3 | | Ruby on Rails | [brakeman](https://brakemanscanner.org) | 10.3 |
| Scala ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.0 (SBT) & 11.9 (Ant, Gradle, Maven) | | Scala ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.0 (SBT) & 11.9 (Ant, Gradle, Maven) |
| TypeScript | [TSLint config security](https://github.com/webschik/tslint-config-security/) | 11.9 | | TypeScript | [TSLint config security](https://github.com/webschik/tslint-config-security/) | 11.9 |
......
# GitLab Conan Repository **(PREMIUM)** # GitLab Conan Repository **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/8248) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5. > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/8248) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.6.
With the GitLab Conan Repository, every With the GitLab Conan Repository, every
project can have its own space to store Conan packages. project can have its own space to store Conan packages.
......
...@@ -21,7 +21,7 @@ module Gitlab ...@@ -21,7 +21,7 @@ module Gitlab
finder_class: MergeRequestsFinder, finder_class: MergeRequestsFinder,
serializer_class: AnalyticsMergeRequestSerializer, serializer_class: AnalyticsMergeRequestSerializer,
includes_for_query: { target_project: [:namespace], author: [] }, includes_for_query: { target_project: [:namespace], author: [] },
columns_for_select: %I[title iid id created_at author_id state target_project_id] columns_for_select: %I[title iid id created_at author_id state_id target_project_id]
} }
}.freeze }.freeze
......
...@@ -200,7 +200,6 @@ module Gitlab ...@@ -200,7 +200,6 @@ module Gitlab
target_project_id: project.id, target_project_id: project.id,
target_branch: Gitlab::Git.ref_name(pull_request.target_branch_name), target_branch: Gitlab::Git.ref_name(pull_request.target_branch_name),
target_branch_sha: pull_request.target_branch_sha, target_branch_sha: pull_request.target_branch_sha,
state: pull_request.state,
state_id: MergeRequest.available_states[pull_request.state], state_id: MergeRequest.available_states[pull_request.state],
author_id: author_id, author_id: author_id,
assignee_id: nil, assignee_id: nil,
......
...@@ -10,7 +10,7 @@ module Gitlab ...@@ -10,7 +10,7 @@ module Gitlab
mr_table[:iid], mr_table[:iid],
mr_table[:id], mr_table[:id],
mr_table[:created_at], mr_table[:created_at],
mr_table[:state], mr_table[:state_id],
mr_table[:author_id]] mr_table[:author_id]]
@order = mr_table[:created_at] @order = mr_table[:created_at]
......
...@@ -10,7 +10,7 @@ module Gitlab ...@@ -10,7 +10,7 @@ module Gitlab
mr_table[:iid], mr_table[:iid],
mr_table[:id], mr_table[:id],
mr_table[:created_at], mr_table[:created_at],
mr_table[:state], mr_table[:state_id],
mr_table[:author_id]] mr_table[:author_id]]
super(*args) super(*args)
......
...@@ -52,7 +52,6 @@ module Gitlab ...@@ -52,7 +52,6 @@ module Gitlab
project_id: project.id, project_id: project.id,
description: description, description: description,
milestone_id: milestone_finder.id_for(issue), milestone_id: milestone_finder.id_for(issue),
state: issue.state,
state_id: ::Issue.available_states[issue.state], state_id: ::Issue.available_states[issue.state],
created_at: issue.created_at, created_at: issue.created_at,
updated_at: issue.updated_at updated_at: issue.updated_at
......
...@@ -54,7 +54,6 @@ module Gitlab ...@@ -54,7 +54,6 @@ module Gitlab
target_project_id: project.id, target_project_id: project.id,
source_branch: pull_request.formatted_source_branch, source_branch: pull_request.formatted_source_branch,
target_branch: pull_request.target_branch, target_branch: pull_request.target_branch,
state: pull_request.state,
state_id: ::MergeRequest.available_states[pull_request.state], state_id: ::MergeRequest.available_states[pull_request.state],
milestone_id: milestone_finder.id_for(pull_request), milestone_id: milestone_finder.id_for(pull_request),
author_id: author_id, author_id: author_id,
......
...@@ -23,7 +23,7 @@ module Gitlab ...@@ -23,7 +23,7 @@ module Gitlab
milestone_id milestone_id
source_branch source_branch
source_project_id source_project_id
state state_id
target_branch target_branch
target_project_id target_project_id
time_estimate time_estimate
...@@ -53,7 +53,8 @@ module Gitlab ...@@ -53,7 +53,8 @@ module Gitlab
human_total_time_spent: merge_request.human_total_time_spent, human_total_time_spent: merge_request.human_total_time_spent,
human_time_estimate: merge_request.human_time_estimate, human_time_estimate: merge_request.human_time_estimate,
assignee_ids: merge_request.assignee_ids, assignee_ids: merge_request.assignee_ids,
assignee_id: merge_request.assignee_ids.first # This key is deprecated assignee_id: merge_request.assignee_ids.first, # This key is deprecated
state: merge_request.state # This key is deprecated
} }
merge_request.attributes.with_indifferent_access.slice(*self.class.safe_hook_attributes) merge_request.attributes.with_indifferent_access.slice(*self.class.safe_hook_attributes)
......
...@@ -275,3 +275,4 @@ ee: ...@@ -275,3 +275,4 @@ ee:
- :unprotect_access_levels - :unprotect_access_levels
- protected_environments: - protected_environments:
- :deploy_access_levels - :deploy_access_levels
- :service_desk_setting
...@@ -7348,6 +7348,9 @@ msgstr "" ...@@ -7348,6 +7348,9 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}" msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr "" msgstr ""
msgid "FeatureFlags|Include additional user IDs"
msgstr ""
msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}" msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr "" msgstr ""
......
...@@ -79,7 +79,8 @@ describe 'Database schema' do ...@@ -79,7 +79,8 @@ describe 'Database schema' do
vulnerability_identifiers: %w[external_id], vulnerability_identifiers: %w[external_id],
vulnerability_scanners: %w[external_id], vulnerability_scanners: %w[external_id],
web_hooks: %w[service_id group_id], web_hooks: %w[service_id group_id],
suggestions: %w[commit_id] suggestions: %w[commit_id],
commit_user_mentions: %w[commit_id]
}.with_indifferent_access.freeze }.with_indifferent_access.freeze
context 'for table' do context 'for table' do
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
"additionalProperties": false "additionalProperties": false
}, },
"_links": { "_links": {
"required": ["merge_requests_url", "issues_url", "edit_url"], "required": ["merge_requests_url", "issues_url"],
"properties": { "properties": {
"merge_requests_url": { "type": "string" }, "merge_requests_url": { "type": "string" },
"issues_url": { "type": "string" }, "issues_url": { "type": "string" },
......
...@@ -26,11 +26,10 @@ ...@@ -26,11 +26,10 @@
"additionalProperties": false "additionalProperties": false
}, },
"_links": { "_links": {
"required": ["merge_requests_url", "issues_url", "edit_url"], "required": ["merge_requests_url", "issues_url"],
"properties": { "properties": {
"merge_requests_url": { "type": "string" }, "merge_requests_url": { "type": "string" },
"issues_url": { "type": "string" }, "issues_url": { "type": "string" }
"edit_url": { "type": "string"}
} }
} }
}, },
......
...@@ -157,6 +157,7 @@ describe ProjectsHelper do ...@@ -157,6 +157,7 @@ describe ProjectsHelper do
allow(helper).to receive(:current_user).and_return(user) allow(helper).to receive(:current_user).and_return(user)
allow(helper).to receive(:can?).with(user, :read_cross_project) { true } allow(helper).to receive(:can?).with(user, :read_cross_project) { true }
allow(user).to receive(:max_member_access_for_project).and_return(40) allow(user).to receive(:max_member_access_for_project).and_return(40)
allow(Gitlab::I18n).to receive(:locale).and_return('es')
end end
it "includes the route" do it "includes the route" do
...@@ -203,6 +204,10 @@ describe ProjectsHelper do ...@@ -203,6 +204,10 @@ describe ProjectsHelper do
expect(helper.project_list_cache_key(project)).to include("pipeline-status/#{project.commit.sha}-success") expect(helper.project_list_cache_key(project)).to include("pipeline-status/#{project.commit.sha}-success")
end end
it "includes the user locale" do
expect(helper.project_list_cache_key(project)).to include('es')
end
it "includes the user max member access" do it "includes the user max member access" do
expect(helper.project_list_cache_key(project)).to include('access:40') expect(helper.project_list_cache_key(project)).to include('access:40')
end end
......
...@@ -99,7 +99,6 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach ...@@ -99,7 +99,6 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach
project_id: project.id, project_id: project.id,
description: 'This is my issue', description: 'This is my issue',
milestone_id: milestone.id, milestone_id: milestone.id,
state: :opened,
state_id: 1, state_id: 1,
created_at: created_at, created_at: created_at,
updated_at: updated_at updated_at: updated_at
...@@ -129,7 +128,6 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach ...@@ -129,7 +128,6 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach
project_id: project.id, project_id: project.id,
description: "*Created by: alice*\n\nThis is my issue", description: "*Created by: alice*\n\nThis is my issue",
milestone_id: milestone.id, milestone_id: milestone.id,
state: :opened,
state_id: 1, state_id: 1,
created_at: created_at, created_at: created_at,
updated_at: updated_at updated_at: updated_at
......
...@@ -94,7 +94,6 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi ...@@ -94,7 +94,6 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
target_project_id: project.id, target_project_id: project.id,
source_branch: 'github/fork/alice/feature', source_branch: 'github/fork/alice/feature',
target_branch: 'master', target_branch: 'master',
state: :merged,
state_id: 3, state_id: 3,
milestone_id: milestone.id, milestone_id: milestone.id,
author_id: user.id, author_id: user.id,
...@@ -140,7 +139,6 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi ...@@ -140,7 +139,6 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
target_project_id: project.id, target_project_id: project.id,
source_branch: 'github/fork/alice/feature', source_branch: 'github/fork/alice/feature',
target_branch: 'master', target_branch: 'master',
state: :merged,
state_id: 3, state_id: 3,
milestone_id: milestone.id, milestone_id: milestone.id,
author_id: project.creator_id, author_id: project.creator_id,
...@@ -187,7 +185,6 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi ...@@ -187,7 +185,6 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
target_project_id: project.id, target_project_id: project.id,
source_branch: 'master-42', source_branch: 'master-42',
target_branch: 'master', target_branch: 'master',
state: :merged,
state_id: 3, state_id: 3,
milestone_id: milestone.id, milestone_id: milestone.id,
author_id: user.id, author_id: user.id,
......
...@@ -18,7 +18,7 @@ describe Gitlab::Import::MergeRequestHelpers, type: :helper do ...@@ -18,7 +18,7 @@ describe Gitlab::Import::MergeRequestHelpers, type: :helper do
target_project_id: project.id, target_project_id: project.id,
source_branch: 'master-42', source_branch: 'master-42',
target_branch: 'master', target_branch: 'master',
state: :merged, state_id: 3,
author_id: user.id, author_id: user.id,
assignee_id: user.id assignee_id: user.id
} }
......
...@@ -432,6 +432,7 @@ project: ...@@ -432,6 +432,7 @@ project:
- downstream_projects - downstream_projects
- upstream_project_subscriptions - upstream_project_subscriptions
- downstream_project_subscriptions - downstream_project_subscriptions
- service_desk_setting
award_emoji: award_emoji:
- awardable - awardable
- user - user
......
...@@ -762,3 +762,6 @@ ZoomMeeting: ...@@ -762,3 +762,6 @@ ZoomMeeting:
- url - url
- created_at - created_at
- updated_at - updated_at
ServiceDeskSetting:
- project_id
- issue_template_key
...@@ -73,11 +73,11 @@ describe Gitlab::MarkdownCache::ActiveRecord::Extension do ...@@ -73,11 +73,11 @@ describe Gitlab::MarkdownCache::ActiveRecord::Extension do
let(:thing) { klass.new(title: markdown, title_html: html, cached_markdown_version: cache_version) } let(:thing) { klass.new(title: markdown, title_html: html, cached_markdown_version: cache_version) }
before do before do
thing.state = 'closed' thing.state_id = 2
thing.save thing.save
end end
it { expect(thing.state).to eq('closed') } it { expect(thing.state_id).to eq(2) }
it { expect(thing.title).to eq(markdown) } it { expect(thing.title).to eq(markdown) }
it { expect(thing.title_html).to eq(html) } it { expect(thing.title_html).to eq(html) }
it { expect(thing.cached_markdown_version).to eq(cache_version) } it { expect(thing.cached_markdown_version).to eq(cache_version) }
......
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20191104142124_nullify_users_role.rb')
describe NullifyUsersRole, :migration do
let(:users) { table(:users) }
before do
allow(Gitlab).to receive(:com?).and_return(true)
users.create!(role: 0, updated_at: '2019-11-04 12:08:00', projects_limit: 0, email: '1')
users.create!(role: 1, updated_at: '2019-11-04 12:08:00', projects_limit: 0, email: '2')
users.create!(role: 0, updated_at: '2019-11-06 12:08:00', projects_limit: 0, email: '3')
migrate!
end
it 'nullifies the role of the user with updated_at < 2019-11-05 12:08:00 and a role of 0' do
expect(users.where(role: nil).count).to eq(1)
expect(users.where(role: nil).first.email).to eq('1')
end
it 'leaves the user with role of 1' do
expect(users.where(role: 1).count).to eq(1)
expect(users.where(role: 1).first.email).to eq('2')
end
it 'leaves the user with updated_at > 2019-11-05 12:08:00' do
expect(users.where(role: 0).count).to eq(1)
expect(users.where(role: 0).first.email).to eq('3')
end
end
...@@ -1045,7 +1045,9 @@ describe Ci::Pipeline, :mailer do ...@@ -1045,7 +1045,9 @@ describe Ci::Pipeline, :mailer do
stage_idx: 0, stage_idx: 0,
status: 'success') status: 'success')
pipeline.process! Ci::ProcessPipelineService
.new(pipeline)
.execute
end end
it 'ignores the previous state' do it 'ignores the previous state' do
......
# frozen_string_literal: true
require 'spec_helper'
# This spec checks if state_id column of issues and merge requests
# are being synced on every save.
# It can be removed in the next release. Check https://gitlab.com/gitlab-org/gitlab-foss/issues/51789 for more information.
describe IssuableStates do
[Issue, MergeRequest].each do |klass|
it "syncs state_id column when #{klass.model_name.human} gets created" do
klass.available_states.each do |state, state_id|
issuable = build(klass.model_name.param_key, state: state.to_s)
issuable.save!
expect(issuable.state_id).to eq(state_id)
end
end
it "syncs state_id column when #{klass.model_name.human} gets updated" do
klass.available_states.each do |state, state_id|
issuable = create(klass.model_name.param_key, state: state.to_s)
issuable.update(state: state)
expect(issuable.state_id).to eq(state_id)
end
end
end
end
...@@ -97,5 +97,11 @@ describe ReleasePresenter do ...@@ -97,5 +97,11 @@ describe ReleasePresenter do
it { is_expected.to be_nil } it { is_expected.to be_nil }
end end
context 'when a user is not allowed to update a release' do
let(:presenter) { described_class.new(release, current_user: guest) }
it { is_expected.to be_nil }
end
end end
end end
...@@ -845,7 +845,7 @@ describe Ci::ProcessPipelineService, '#execute' do ...@@ -845,7 +845,7 @@ describe Ci::ProcessPipelineService, '#execute' do
end end
def process_pipeline def process_pipeline
described_class.new(pipeline.project, user).execute(pipeline) described_class.new(pipeline).execute
end end
def all_builds def all_builds
......
...@@ -223,7 +223,7 @@ describe Ci::RetryPipelineService, '#execute' do ...@@ -223,7 +223,7 @@ describe Ci::RetryPipelineService, '#execute' do
end end
it 'reprocesses the pipeline' do it 'reprocesses the pipeline' do
expect(pipeline).to receive(:process!) expect_any_instance_of(Ci::ProcessPipelineService).to receive(:execute)
service.execute(pipeline) service.execute(pipeline)
end end
......
...@@ -8,7 +8,11 @@ def webmock_allowed_hosts ...@@ -8,7 +8,11 @@ def webmock_allowed_hosts
if ENV.key?('ELASTIC_URL') if ENV.key?('ELASTIC_URL')
hosts << URI.parse(ENV['ELASTIC_URL']).host hosts << URI.parse(ENV['ELASTIC_URL']).host
end end
end.uniq
if Gitlab.config.webpack&.dev_server&.enabled
hosts << Gitlab.config.webpack.dev_server.host
end
end.compact.uniq
end end
WebMock.disable_net_connect!(allow_localhost: true, allow: webmock_allowed_hosts) WebMock.disable_net_connect!(allow_localhost: true, allow: webmock_allowed_hosts)
...@@ -8,7 +8,7 @@ describe PipelineProcessWorker do ...@@ -8,7 +8,7 @@ describe PipelineProcessWorker do
let(:pipeline) { create(:ci_pipeline) } let(:pipeline) { create(:ci_pipeline) }
it 'processes pipeline' do it 'processes pipeline' do
expect_any_instance_of(Ci::Pipeline).to receive(:process!) expect_any_instance_of(Ci::ProcessPipelineService).to receive(:execute)
described_class.new.perform(pipeline.id) described_class.new.perform(pipeline.id)
end end
...@@ -17,7 +17,7 @@ describe PipelineProcessWorker do ...@@ -17,7 +17,7 @@ describe PipelineProcessWorker do
let(:build) { create(:ci_build, pipeline: pipeline, name: 'my-build') } let(:build) { create(:ci_build, pipeline: pipeline, name: 'my-build') }
it 'processes pipeline with a list of builds' do it 'processes pipeline with a list of builds' do
expect_any_instance_of(Ci::Pipeline).to receive(:process!) expect_any_instance_of(Ci::ProcessPipelineService).to receive(:execute)
.with([build.id]) .with([build.id])
described_class.new.perform(pipeline.id, [build.id]) described_class.new.perform(pipeline.id, [build.id])
......
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