Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
eb08c8e6f8
commit
3bb41f7bdd
59 changed files with 481 additions and 171 deletions
|
@ -105,14 +105,6 @@ Lint/StructNewOverride:
|
|||
- 'app/serializers/environment_serializer.rb'
|
||||
- 'lib/gitlab/ci/pipeline/duration.rb'
|
||||
|
||||
# Offense count: 7
|
||||
Lint/UriEscapeUnescape:
|
||||
Exclude:
|
||||
- 'app/controllers/application_controller.rb'
|
||||
- 'app/models/project_services/drone_ci_service.rb'
|
||||
- 'spec/lib/google_api/auth_spec.rb'
|
||||
- 'spec/requests/api/files_spec.rb'
|
||||
|
||||
# Offense count: 65
|
||||
# Cop supports --auto-correct.
|
||||
Migration/DepartmentName:
|
||||
|
@ -1038,18 +1030,6 @@ Rails/SaveBang:
|
|||
- 'spec/models/clusters/applications/helm_spec.rb'
|
||||
- 'spec/models/commit_spec.rb'
|
||||
- 'spec/models/commit_status_spec.rb'
|
||||
- 'spec/models/concerns/avatarable_spec.rb'
|
||||
- 'spec/models/concerns/bulk_insertable_associations_spec.rb'
|
||||
- 'spec/models/concerns/cache_markdown_field_spec.rb'
|
||||
- 'spec/models/concerns/case_sensitivity_spec.rb'
|
||||
- 'spec/models/concerns/featurable_spec.rb'
|
||||
- 'spec/models/concerns/issuable_spec.rb'
|
||||
- 'spec/models/concerns/mentionable_spec.rb'
|
||||
- 'spec/models/concerns/milestoneable_spec.rb'
|
||||
- 'spec/models/concerns/milestoneish_spec.rb'
|
||||
- 'spec/models/concerns/routable_spec.rb'
|
||||
- 'spec/models/concerns/subscribable_spec.rb'
|
||||
- 'spec/models/concerns/token_authenticatable_spec.rb'
|
||||
- 'spec/models/container_repository_spec.rb'
|
||||
- 'spec/models/deploy_keys_project_spec.rb'
|
||||
- 'spec/models/deploy_token_spec.rb'
|
||||
|
|
|
@ -1 +1 @@
|
|||
af8db5cecac045e869d6ee9572e9f75a3ad14d86
|
||||
9096b269b6abfa8cbe8cf6c48a03e3bec93d47ae
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
/* eslint-disable vue/no-v-html */
|
||||
import { mapActions } from 'vuex';
|
||||
import { escape } from 'lodash';
|
||||
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
|
||||
|
||||
import { s__, __, sprintf } from '~/locale';
|
||||
import { truncateSha } from '~/lib/utils/text_utility';
|
||||
|
@ -17,6 +17,9 @@ export default {
|
|||
noteEditedText,
|
||||
noteHeader,
|
||||
},
|
||||
directives: {
|
||||
SafeHtml,
|
||||
},
|
||||
props: {
|
||||
discussion: {
|
||||
type: Object,
|
||||
|
@ -113,7 +116,7 @@ export default {
|
|||
:expanded="discussion.expanded"
|
||||
@toggleHandler="toggleDiscussionHandler"
|
||||
>
|
||||
<span v-html="headerText"></span>
|
||||
<span v-safe-html="headerText"></span>
|
||||
</note-header>
|
||||
<note-edited-text
|
||||
v-if="discussion.resolved"
|
||||
|
|
|
@ -98,7 +98,7 @@ export const nugetSetupCommand = ({ nugetPath }) =>
|
|||
|
||||
export const pypiPipCommand = ({ pypiPath, packageEntity }) =>
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
`pip install ${packageEntity.name} --index-url ${pypiPath}`;
|
||||
`pip install ${packageEntity.name} --extra-index-url ${pypiPath}`;
|
||||
|
||||
export const pypiSetupCommand = ({ pypiSetupPath }) => `[gitlab]
|
||||
repository = ${pypiSetupPath}
|
||||
|
|
|
@ -484,7 +484,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def set_page_title_header
|
||||
# Per https://tools.ietf.org/html/rfc5987, headers need to be ISO-8859-1, not UTF-8
|
||||
response.headers['Page-Title'] = URI.escape(page_title('GitLab'))
|
||||
response.headers['Page-Title'] = Addressable::URI.encode_component(page_title('GitLab'))
|
||||
end
|
||||
|
||||
def set_current_admin(&block)
|
||||
|
|
|
@ -8,24 +8,24 @@ module Types
|
|||
field :notes, Types::Notes::NoteType.connection_type, null: false, description: "All notes on this noteable"
|
||||
field :discussions, Types::Notes::DiscussionType.connection_type, null: false, description: "All discussions on this noteable"
|
||||
|
||||
definition_methods do
|
||||
def resolve_type(object, context)
|
||||
case object
|
||||
when Issue
|
||||
Types::IssueType
|
||||
when MergeRequest
|
||||
Types::MergeRequestType
|
||||
when Snippet
|
||||
Types::SnippetType
|
||||
when ::DesignManagement::Design
|
||||
Types::DesignManagement::DesignType
|
||||
when ::AlertManagement::Alert
|
||||
Types::AlertManagement::AlertType
|
||||
else
|
||||
raise "Unknown GraphQL type for #{object}"
|
||||
end
|
||||
def self.resolve_type(object, context)
|
||||
case object
|
||||
when Issue
|
||||
Types::IssueType
|
||||
when MergeRequest
|
||||
Types::MergeRequestType
|
||||
when Snippet
|
||||
Types::SnippetType
|
||||
when ::DesignManagement::Design
|
||||
Types::DesignManagement::DesignType
|
||||
when ::AlertManagement::Alert
|
||||
Types::AlertManagement::AlertType
|
||||
else
|
||||
raise "Unknown GraphQL type for #{object}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Types::Notes::NoteableType.prepend_if_ee('::EE::Types::Notes::NoteableType')
|
||||
|
|
|
@ -42,7 +42,7 @@ class DroneCiService < CiService
|
|||
def commit_status_path(sha, ref)
|
||||
Gitlab::Utils.append_path(
|
||||
drone_url,
|
||||
"gitlab/#{project.full_path}/commits/#{sha}?branch=#{URI.encode(ref.to_s)}&access_token=#{token}")
|
||||
"gitlab/#{project.full_path}/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}&access_token=#{token}")
|
||||
end
|
||||
|
||||
def commit_status(sha, ref)
|
||||
|
@ -75,7 +75,7 @@ class DroneCiService < CiService
|
|||
def build_page(sha, ref)
|
||||
Gitlab::Utils.append_path(
|
||||
drone_url,
|
||||
"gitlab/#{project.full_path}/redirect/commits/#{sha}?branch=#{URI.encode(ref.to_s)}")
|
||||
"gitlab/#{project.full_path}/redirect/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}")
|
||||
end
|
||||
|
||||
def title
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
.file-buttons
|
||||
- if is_markdown
|
||||
= render 'shared/blob/markdown_buttons', show_fullscreen_button: false
|
||||
= button_tag class: 'soft-wrap-toggle btn', type: 'button', tabindex: '-1' do
|
||||
= button_tag class: 'soft-wrap-toggle btn gl-button', type: 'button', tabindex: '-1' do
|
||||
%span.no-wrap
|
||||
= custom_icon('icon_no_wrap')
|
||||
No wrap
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
= render 'shared/new_commit_form', placeholder: _("Add new directory")
|
||||
|
||||
.form-actions
|
||||
= submit_tag _("Create directory"), class: 'btn btn-success'
|
||||
= link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
|
||||
= submit_tag _("Create directory"), class: 'btn gl-button btn-success'
|
||||
= link_to "Cancel", '#', class: "btn gl-button btn-cancel", "data-dismiss" => "modal"
|
||||
|
||||
= render 'shared/projects/edit_information'
|
||||
|
|
|
@ -12,5 +12,5 @@
|
|||
|
||||
.form-group.row
|
||||
.offset-sm-2.col-sm-10
|
||||
= button_tag 'Delete file', class: 'btn btn-remove btn-remove-file'
|
||||
= link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
|
||||
= button_tag 'Delete file', class: 'btn gl-button btn-danger btn-remove-file'
|
||||
= link_to "Cancel", '#', class: "btn gl-button btn-cancel", "data-dismiss" => "modal"
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
= render 'shared/new_commit_form', placeholder: placeholder
|
||||
|
||||
.form-actions
|
||||
= button_tag class: 'btn btn-success btn-upload-file', id: 'submit-all', type: 'button' do
|
||||
= button_tag class: 'btn gl-button btn-success btn-upload-file', id: 'submit-all', type: 'button' do
|
||||
= icon('spin spinner', class: 'js-loading-icon hidden' )
|
||||
= button_title
|
||||
= link_to _("Cancel"), '#', class: "btn btn-cancel", "data-dismiss" => "modal"
|
||||
= link_to _("Cancel"), '#', class: "btn gl-button btn-cancel", "data-dismiss" => "modal"
|
||||
|
||||
= render 'shared/projects/edit_information'
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
.btn-group.js-blob-viewer-switcher.ml-2{ role: "group" }>
|
||||
- simple_label = "Display #{simple_viewer.switcher_title}"
|
||||
%button.btn.btn-default.btn-sm.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => simple_label, title: simple_label, data: { viewer: 'simple', container: 'body' } }>
|
||||
%button.btn.gl-button.btn-default.btn-sm.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => simple_label, title: simple_label, data: { viewer: 'simple', container: 'body' } }>
|
||||
= sprite_icon(simple_viewer.switcher_icon)
|
||||
|
||||
- rich_label = "Display #{rich_viewer.switcher_title}"
|
||||
%button.btn.btn-default.btn-sm.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => rich_label, title: rich_label, data: { viewer: 'rich', container: 'body' } }>
|
||||
%button.btn.gl-button.btn-default.btn-sm.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => rich_label, title: rich_label, data: { viewer: 'rich', container: 'body' } }>
|
||||
= sprite_icon(rich_viewer.switcher_icon)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
- @gfm_form = Feature.enabled?(:feature_flags_issue_links, @project, default_enabled: true)
|
||||
- @gfm_form = true
|
||||
|
||||
- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
|
||||
- breadcrumb_title @feature_flag.name
|
||||
|
|
5
changelogs/unreleased/42916-pypi-install-command.yml
Normal file
5
changelogs/unreleased/42916-pypi-install-command.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update pypi install command to work with external dependencies
|
||||
merge_request: 42916
|
||||
author:
|
||||
type: changed
|
5
changelogs/unreleased/42917_golang_vendor_templates.yml
Normal file
5
changelogs/unreleased/42917_golang_vendor_templates.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update golang version in vendored Dockerfile template
|
||||
merge_request: 42917
|
||||
author:
|
||||
type: added
|
5
changelogs/unreleased/gitlab_buttons_projects_blob.yml
Normal file
5
changelogs/unreleased/gitlab_buttons_projects_blob.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Apply GitLab UI button styles to HAML buttons app/views/projects/blob
|
||||
merge_request: 42991
|
||||
author: Andrei Kyrnich @kyrnich
|
||||
type: other
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Validate not null file_store field on packages_package_files to maintain data
|
||||
integrity
|
||||
merge_request: 42400
|
||||
author:
|
||||
type: added
|
5
changelogs/unreleased/rails-save-bang-36.yml
Normal file
5
changelogs/unreleased/rails-save-bang-36.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fixes Rails/SaveBang cop for spec files in spec/models/concerns/*
|
||||
merge_request: 42942
|
||||
author: Rajendra Kadam
|
||||
type: other
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class EnsureFilledFileStoreOnPackageFiles < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
BACKGROUND_MIGRATION_CLASS = 'SetNullPackageFilesFileStoreToLocalValue'
|
||||
BATCH_SIZE = 5_000
|
||||
LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
module Packages
|
||||
class PackageFile < ActiveRecord::Base
|
||||
self.table_name = 'packages_package_files'
|
||||
|
||||
include ::EachBatch
|
||||
end
|
||||
end
|
||||
|
||||
def up
|
||||
Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
|
||||
|
||||
# Do a manual update in case we lost BG jobs. The expected record count should be 0 or very low.
|
||||
Packages::PackageFile.where(file_store: nil).each_batch(of: BATCH_SIZE) do |batch, index|
|
||||
batch.update_all(file_store: LOCAL_STORE)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ValidateNotNullFileStoreOnPackageFiles < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
# Remove index which was only added to fill file_store
|
||||
INDEX_NAME = 'index_packages_package_files_file_store_is_null'
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
validate_not_null_constraint :packages_package_files, :file_store
|
||||
|
||||
remove_concurrent_index_by_name :packages_package_files, INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index :packages_package_files, :id, where: 'file_store IS NULL', name: INDEX_NAME
|
||||
end
|
||||
end
|
1
db/schema_migrations/20200915185707
Normal file
1
db/schema_migrations/20200915185707
Normal file
|
@ -0,0 +1 @@
|
|||
e1ae80d6f0a6372bb329d45257d9a0a8ca5b6a83718d2a10ee295b8c4c97f60e
|
1
db/schema_migrations/20200915191156
Normal file
1
db/schema_migrations/20200915191156
Normal file
|
@ -0,0 +1 @@
|
|||
d8ddec6b234d59b3b85705dfa7b724d3be4974bfa57fae70aa5c2dbdd2e73cfa
|
|
@ -14123,7 +14123,8 @@ CREATE TABLE packages_package_files (
|
|||
verified_at timestamp with time zone,
|
||||
verification_failure character varying(255),
|
||||
verification_retry_count integer,
|
||||
verification_checksum bytea
|
||||
verification_checksum bytea,
|
||||
CONSTRAINT check_4c5e6bb0b3 CHECK ((file_store IS NOT NULL))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE packages_package_files_id_seq
|
||||
|
@ -18084,9 +18085,6 @@ ALTER TABLE design_management_designs
|
|||
ALTER TABLE vulnerability_scanners
|
||||
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
|
||||
|
||||
ALTER TABLE packages_package_files
|
||||
ADD CONSTRAINT check_4c5e6bb0b3 CHECK ((file_store IS NOT NULL)) NOT VALID;
|
||||
|
||||
ALTER TABLE group_import_states
|
||||
ADD CONSTRAINT check_cda75c7c3f CHECK ((user_id IS NOT NULL)) NOT VALID;
|
||||
|
||||
|
@ -20684,8 +20682,6 @@ CREATE INDEX index_packages_nuget_dl_metadata_on_dependency_link_id ON packages_
|
|||
|
||||
CREATE UNIQUE INDEX index_packages_on_project_id_name_version_unique_when_generic ON packages_packages USING btree (project_id, name, version) WHERE (package_type = 7);
|
||||
|
||||
CREATE INDEX index_packages_package_files_file_store_is_null ON packages_package_files USING btree (id) WHERE (file_store IS NULL);
|
||||
|
||||
CREATE INDEX index_packages_package_files_on_file_store ON packages_package_files USING btree (file_store);
|
||||
|
||||
CREATE INDEX index_packages_package_files_on_package_id_and_file_name ON packages_package_files USING btree (package_id, file_name);
|
||||
|
|
|
@ -18733,7 +18733,7 @@ type VulnerabilitiesCountByDayEdge {
|
|||
"""
|
||||
Represents a vulnerability
|
||||
"""
|
||||
type Vulnerability {
|
||||
type Vulnerability implements Noteable {
|
||||
"""
|
||||
Description of the vulnerability
|
||||
"""
|
||||
|
@ -18744,6 +18744,31 @@ type Vulnerability {
|
|||
"""
|
||||
detectedAt: Time!
|
||||
|
||||
"""
|
||||
All discussions on this noteable
|
||||
"""
|
||||
discussions(
|
||||
"""
|
||||
Returns the elements in the list that come after the specified cursor.
|
||||
"""
|
||||
after: String
|
||||
|
||||
"""
|
||||
Returns the elements in the list that come before the specified cursor.
|
||||
"""
|
||||
before: String
|
||||
|
||||
"""
|
||||
Returns the first _n_ elements from the list.
|
||||
"""
|
||||
first: Int
|
||||
|
||||
"""
|
||||
Returns the last _n_ elements from the list.
|
||||
"""
|
||||
last: Int
|
||||
): DiscussionConnection!
|
||||
|
||||
"""
|
||||
GraphQL ID of the vulnerability
|
||||
"""
|
||||
|
@ -18789,6 +18814,31 @@ type Vulnerability {
|
|||
"""
|
||||
location: VulnerabilityLocation
|
||||
|
||||
"""
|
||||
All notes on this noteable
|
||||
"""
|
||||
notes(
|
||||
"""
|
||||
Returns the elements in the list that come after the specified cursor.
|
||||
"""
|
||||
after: String
|
||||
|
||||
"""
|
||||
Returns the elements in the list that come before the specified cursor.
|
||||
"""
|
||||
before: String
|
||||
|
||||
"""
|
||||
Returns the first _n_ elements from the list.
|
||||
"""
|
||||
first: Int
|
||||
|
||||
"""
|
||||
Returns the last _n_ elements from the list.
|
||||
"""
|
||||
last: Int
|
||||
): NoteConnection!
|
||||
|
||||
"""
|
||||
Primary identifier of the vulnerability.
|
||||
"""
|
||||
|
|
|
@ -33910,6 +33910,11 @@
|
|||
"kind": "OBJECT",
|
||||
"name": "Snippet",
|
||||
"ofType": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Vulnerability",
|
||||
"ofType": null
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -54817,6 +54822,63 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "discussions",
|
||||
"description": "All discussions on this noteable",
|
||||
"args": [
|
||||
{
|
||||
"name": "after",
|
||||
"description": "Returns the elements in the list that come after the specified cursor.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "before",
|
||||
"description": "Returns the elements in the list that come before the specified cursor.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "first",
|
||||
"description": "Returns the first _n_ elements from the list.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "last",
|
||||
"description": "Returns the last _n_ elements from the list.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "DiscussionConnection",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"description": "GraphQL ID of the vulnerability",
|
||||
|
@ -54942,6 +55004,63 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "notes",
|
||||
"description": "All notes on this noteable",
|
||||
"args": [
|
||||
{
|
||||
"name": "after",
|
||||
"description": "Returns the elements in the list that come after the specified cursor.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "before",
|
||||
"description": "Returns the elements in the list that come before the specified cursor.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "first",
|
||||
"description": "Returns the first _n_ elements from the list.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "last",
|
||||
"description": "Returns the last _n_ elements from the list.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "NoteConnection",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "primaryIdentifier",
|
||||
"description": "Primary identifier of the vulnerability.",
|
||||
|
@ -55111,7 +55230,11 @@
|
|||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "Noteable",
|
||||
"ofType": null
|
||||
}
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
|
|
|
@ -68,7 +68,7 @@ microservice_a:
|
|||
trigger:
|
||||
include:
|
||||
- local: path/to/microservice_a.yml
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
```
|
||||
|
||||
NOTE: **Note:**
|
||||
|
@ -82,7 +82,7 @@ microservice_a:
|
|||
trigger:
|
||||
include:
|
||||
- local: path/to/microservice_a.yml
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
strategy: depend
|
||||
```
|
||||
|
||||
|
|
|
@ -16,11 +16,19 @@ In either case, an outcome of the experiment should be posted to the issue with
|
|||
|
||||
## Code reviews
|
||||
|
||||
Since the code of experiments will not be part of the codebase for a long time and we want to iterate fast to retrieve data, the code quality of experiments might sometimes not fulfill our standards but should not negatively impact the availability of GitLab whether the experiment is running or not.
|
||||
Initially experiments will only be deployed to a fraction of users but we still want a flawless experience for those users. Therefore, experiments still require tests.
|
||||
Experiments' code quality can fail our standards for several reasons. These
|
||||
reasons can include not being added to the codebase for a long time, or because
|
||||
of fast iteration to retrieve data. However, having the experiment run (or not
|
||||
run) shouldn't impact GitLab's availability. To avoid or identify issues,
|
||||
experiments are initially deployed to a small number of users. Regardless,
|
||||
experiments still need tests.
|
||||
|
||||
For reviewers and maintainers: if you find code that would usually not make it through the review, but is temporarily acceptable, please mention your concerns but note that it's not necessary to change.
|
||||
The author then adds a comment to this piece of code and adds a link to the issue that resolves the experiment. If the experiment is successful and becomes part of the product these follow up issues should be addressed.
|
||||
If, as a reviewer or maintainer, you find code that would usually fail review
|
||||
but is acceptable for now, mention your concerns with a note that there's no
|
||||
need to change the code. The author can then add a comment to this piece of code
|
||||
and link to the issue that resolves the experiment. If the experiment is
|
||||
successful and becomes part of the product, any follow up issues should be
|
||||
addressed.
|
||||
|
||||
## How to create an A/B test
|
||||
|
||||
|
|
|
@ -352,32 +352,8 @@ end
|
|||
|
||||
## Feature Flag Related Issues **(PREMIUM)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2.
|
||||
> - It's deployed behind a feature flag, enabled by default.
|
||||
> - It's enabled on GitLab.com.
|
||||
> - It can't be enabled or disabled per-project
|
||||
> - It's recommended for production use.
|
||||
> - For GitLab self-managed instances, GitLab administrators can opt to disable it.
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2.
|
||||
|
||||
You can link related issues to a feature flag. In the **Linked issues** section, click the `+` button and input the issue reference number or the full URL of the issue.
|
||||
|
||||
This feature is similar to the [related issues](../user/project/issues/related_issues.md) feature.
|
||||
|
||||
### Enable or disable Feature Flag Related Issues **(CORE ONLY)**
|
||||
|
||||
Feature Flag Related Issues is under development but ready for production use.
|
||||
It is deployed behind a feature flag that is **enabled by default**.
|
||||
[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
|
||||
can opt to disable it for your instance.
|
||||
|
||||
To disable it:
|
||||
|
||||
```ruby
|
||||
Feature.disable(:feature_flags_issue_links)
|
||||
```
|
||||
|
||||
To enable it:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:feature_flags_issue_links)
|
||||
```
|
||||
|
|
|
@ -84,7 +84,7 @@ when you receive notification that the alert is resolved.
|
|||
|
||||
## Create an incident manually
|
||||
|
||||
If you have at least Developer [permissions](../../user/permissions.md), to create an Incident, you have two options.
|
||||
If you have at least Guest [permissions](../../user/permissions.md), to create an Incident, you have two options.
|
||||
|
||||
### From the Incidents List
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
Administrators have access to instance-wide analytics, as shown in **Admin Area > Analytics**.
|
||||
|
||||
There are two kinds of statistics:
|
||||
There are several kinds of statistics:
|
||||
|
||||
- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage.
|
||||
- [Instance Statistics](instance_statistics.md): Shows how much data your instance contains, and how that is changing.
|
||||
- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time.
|
||||
|
|
18
doc/user/admin_area/analytics/instance_statistics.md
Normal file
18
doc/user/admin_area/analytics/instance_statistics.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Instance Statistics
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235754) in GitLab 13.4.
|
||||
|
||||
Instance Statistics gives you an overview of how much data your instance contains, and how quickly this volume is changing over time.
|
||||
|
||||
## Total counts
|
||||
|
||||
At the top of the page, Instance Statistics shows total counts for:
|
||||
|
||||
- Users
|
||||
- Projects
|
||||
- Groups
|
||||
- Issues
|
||||
- Merge Requests
|
||||
- Pipelines
|
||||
|
||||
These figures can be useful for understanding how much data your instance contains in total.
|
Binary file not shown.
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 30 KiB |
|
@ -22,10 +22,10 @@ Testing (SAST), and Secret Detection by adding the following to your `.gitlab-ci
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: Dependency-Scanning.gitlab-ci.yml
|
||||
- template: License-Scanning.gitlab-ci.yml
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Secret-Detection.gitlab-ci.yml
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
- template: Security/License-Scanning.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
- template: Security/Secret-Detection.gitlab-ci.yml
|
||||
```
|
||||
|
||||
To add Dynamic Application Security Testing (DAST) scanning, add the following to your
|
||||
|
@ -33,7 +33,7 @@ To add Dynamic Application Security Testing (DAST) scanning, add the following t
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: DAST.gitlab-ci.yml
|
||||
- template: Security/DAST.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
DAST_WEBSITE: https://staging.example.com
|
||||
|
@ -449,7 +449,7 @@ To fix this issue, you can either:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
template: SAST.gitlab-ci.yml
|
||||
template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
spotbugs-sast:
|
||||
stage: unit-tests
|
||||
|
@ -490,7 +490,7 @@ would look similar to:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
# Ensure that the scanning is only executed on master or merge requests
|
||||
spotbugs-sast:
|
||||
|
@ -505,7 +505,7 @@ would be written as follows:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
# Ensure that the scanning is only executed on master or merge requests
|
||||
spotbugs-sast:
|
||||
|
@ -519,7 +519,7 @@ it would look similar to:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
# Ensure that the scanning is not executed on tags
|
||||
spotbugs-sast:
|
||||
|
@ -531,7 +531,7 @@ To transition to the new `rules` syntax, the override would be rewritten as:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
# Ensure that the scanning is not executed on tags
|
||||
spotbugs-sast:
|
||||
|
|
|
@ -53,7 +53,7 @@ In `.gitlab-ci.yml` define:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SECURE_ANALYZERS_PREFIX: my-docker-registry/gl-images
|
||||
|
@ -70,7 +70,7 @@ In `.gitlab-ci.yml` define:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SAST_DEFAULT_ANALYZERS: "bandit,flawfinder"
|
||||
|
@ -86,7 +86,7 @@ default analyzers. In `.gitlab-ci.yml` define:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SAST_DEFAULT_ANALYZERS: ""
|
||||
|
|
|
@ -169,7 +169,7 @@ set the `SAST_GOSEC_LEVEL` variable to `2`:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SAST_GOSEC_LEVEL: 2
|
||||
|
@ -191,7 +191,7 @@ inclusion and specify any additional keys under it. For example, this enables `F
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
spotbugs-sast:
|
||||
variables:
|
||||
|
@ -222,7 +222,7 @@ Kubesec analyzer. In `.gitlab-ci.yml`, define:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SCAN_KUBERNETES_MANIFESTS: "true"
|
||||
|
@ -248,7 +248,7 @@ stages:
|
|||
- test
|
||||
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
build:
|
||||
stage: build
|
||||
|
@ -525,7 +525,7 @@ Add the following configuration to your `.gitlab-ci.yml` file. You must replace
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SECURE_ANALYZERS_PREFIX: "localhost:5000/analyzers"
|
||||
|
|
|
@ -274,7 +274,7 @@ Where:
|
|||
Install the latest version of a package using the following command:
|
||||
|
||||
```shell
|
||||
pip install --index-url https://__token__:<personal_access_token>@gitlab.com/api/v4/projects/<project_id>/packages/pypi/simple --no-deps <package_name>
|
||||
pip install --extra-index-url https://__token__:<personal_access_token>@gitlab.com/api/v4/projects/<project_id>/packages/pypi/simple --no-deps <package_name>
|
||||
```
|
||||
|
||||
Where:
|
||||
|
@ -287,7 +287,7 @@ If you were following the guide above and want to test installing the
|
|||
`MyPyPiPackage` package, you can run the following:
|
||||
|
||||
```shell
|
||||
pip install mypypipackage --no-deps --index-url https://__token__:<personal_access_token>@gitlab.com/api/v4/projects/<your_project_id>/packages/pypi/simple
|
||||
pip install mypypipackage --no-deps --extra-index-url https://__token__:<personal_access_token>@gitlab.com/api/v4/projects/<your_project_id>/packages/pypi/simple
|
||||
```
|
||||
|
||||
This should result in the following:
|
||||
|
|
|
@ -124,3 +124,24 @@ If you are running a self-managed instance of GitLab (GitLab Community Edition a
|
|||
[follow the administration steps](../../../administration/pages/index.md) to configure Pages.
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a [video tutorial](https://www.youtube.com/watch?v=dD8c7WNcc6s) about how to get started with GitLab Pages administration.
|
||||
|
||||
## Security for GitLab Pages
|
||||
|
||||
If your username is `foo`, your GitLab Pages website is located at `foo.gitlab.io`.
|
||||
GitLab allows usernames to contain a `.`, so a user named `bar.foo` could create
|
||||
a GitLab Pages website `bar.foo.gitlab.io` that effectively is a subdomain of your
|
||||
`foo.gitlab.io` website. Be careful if you use JavaScript to set cookies for your website.
|
||||
The safe way to manually set cookies with JavaScript is to not specify the `domain` at all:
|
||||
|
||||
```javascript
|
||||
// Safe: This cookie is only visible to foo.gitlab.io
|
||||
document.cookie = "key=value";
|
||||
|
||||
// Unsafe: This cookie is visible to foo.gitlab.io and its subdomains,
|
||||
// regardless of the presence of the leading dot.
|
||||
document.cookie = "key=value;domain=.foo.gitlab.io";
|
||||
document.cookie = "key=value;domain=foo.gitlab.io";
|
||||
```
|
||||
|
||||
This issue doesn't affect users with a custom domain, or users who don't set any
|
||||
cookies manually with JavaScript.
|
||||
|
|
|
@ -10,7 +10,7 @@ module Gitlab
|
|||
MAX_LINE_LENGTH = 72
|
||||
MAX_CHANGED_FILES_IN_COMMIT = 3
|
||||
MAX_CHANGED_LINES_IN_COMMIT = 30
|
||||
SHORT_REFERENCE_REGEX = %r{([\w\-\/]+)?(#|!|&|%)\d+\b}.freeze
|
||||
SHORT_REFERENCE_REGEX = %r{([\w\-\/]+)?(?<!`)(#|!|&|%)\d+(?<!`)}.freeze
|
||||
DEFAULT_SUBJECT_DESCRIPTION = 'commit subject'
|
||||
WIP_PREFIX = 'WIP: '
|
||||
PROBLEMS = {
|
||||
|
|
|
@ -19,8 +19,8 @@ module Grafana
|
|||
# @param name [String] Unique identifier for a Grafana datasource
|
||||
def get_datasource(name:)
|
||||
# CGI#escape formats strings such that the Grafana endpoint
|
||||
# will not recognize the dashboard name. Preferring URI#escape.
|
||||
http_get("#{@api_url}/api/datasources/name/#{URI.escape(name)}") # rubocop:disable Lint/UriEscapeUnescape
|
||||
# will not recognize the dashboard name. Prefer Addressable::URI#encode_component.
|
||||
http_get("#{@api_url}/api/datasources/name/#{Addressable::URI.encode_component(name)}")
|
||||
end
|
||||
|
||||
# @param datasource_id [String] Grafana ID for the datasource
|
||||
|
|
|
@ -69,7 +69,7 @@ describe('Getters PackageDetails Store', () => {
|
|||
const nugetInstallationCommandStr = `nuget install ${nugetPackage.name} -Source "GitLab"`;
|
||||
const nugetSetupCommandStr = `nuget source Add -Name "GitLab" -Source "${registryUrl}" -UserName <your_username> -Password <your_token>`;
|
||||
|
||||
const pypiPipCommandStr = `pip install ${pypiPackage.name} --index-url ${registryUrl}`;
|
||||
const pypiPipCommandStr = `pip install ${pypiPackage.name} --extra-index-url ${registryUrl}`;
|
||||
const composerRegistryIncludeStr = '{"type":"composer","url":"foo"}';
|
||||
const composerPackageIncludeStr = JSON.stringify({
|
||||
[packageWithoutBuildInfo.name]: packageWithoutBuildInfo.version,
|
||||
|
|
|
@ -323,6 +323,16 @@ RSpec.describe Gitlab::Danger::CommitLinter do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when message includes a value that is surrounded by backticks' do
|
||||
let(:commit_message) { "A commit message `%20`" }
|
||||
|
||||
it 'does not add a problem' do
|
||||
expect(commit_linter).not_to receive(:add_problem)
|
||||
|
||||
commit_linter.lint
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message includes a short reference' do
|
||||
[
|
||||
'A commit message to fix #1234',
|
||||
|
@ -336,7 +346,9 @@ RSpec.describe Gitlab::Danger::CommitLinter do
|
|||
'A commit message to fix gitlab-org/gitlab#1234',
|
||||
'A commit message to fix gitlab-org/gitlab!1234',
|
||||
'A commit message to fix gitlab-org/gitlab&1234',
|
||||
'A commit message to fix gitlab-org/gitlab%1234'
|
||||
'A commit message to fix gitlab-org/gitlab%1234',
|
||||
'A commit message to fix "gitlab-org/gitlab%1234"',
|
||||
'A commit message to fix `gitlab-org/gitlab%1234'
|
||||
].each do |message|
|
||||
let(:commit_message) { message }
|
||||
|
||||
|
|
|
@ -12,12 +12,12 @@ RSpec.describe GoogleApi::Auth do
|
|||
end
|
||||
|
||||
describe '#authorize_url' do
|
||||
subject { client.authorize_url }
|
||||
subject { Addressable::URI.parse(client.authorize_url) }
|
||||
|
||||
it 'returns authorize_url' do
|
||||
is_expected.to start_with('https://accounts.google.com/o/oauth2')
|
||||
is_expected.to include(URI.encode(redirect_uri, URI::PATTERN::RESERVED))
|
||||
is_expected.to include(URI.encode(redirect_to, URI::PATTERN::RESERVED))
|
||||
expect(subject.to_s).to start_with('https://accounts.google.com/o/oauth2')
|
||||
expect(subject.query_values['state']).to eq(redirect_to)
|
||||
expect(subject.query_values['redirect_uri']).to eq(redirect_uri)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require Rails.root.join('db', 'post_migrate', '20200915185707_ensure_filled_file_store_on_package_files.rb')
|
||||
|
||||
RSpec.describe EnsureFilledFileStoreOnPackageFiles, schema: 20200910175553 do
|
||||
let!(:packages_package_files) { table(:packages_package_files) }
|
||||
let!(:packages_packages) { table(:packages_packages) }
|
||||
let!(:namespaces) { table(:namespaces) }
|
||||
let!(:projects) { table(:projects) }
|
||||
let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
|
||||
let!(:project) { projects.create!(namespace_id: namespace.id) }
|
||||
let!(:package) { packages_packages.create!(project_id: project.id, name: 'bar', package_type: 1) }
|
||||
|
||||
before do
|
||||
constraint_name = 'check_4c5e6bb0b3'
|
||||
|
||||
# In order to insert a row with a NULL to fill.
|
||||
ActiveRecord::Base.connection.execute "ALTER TABLE packages_package_files DROP CONSTRAINT #{constraint_name}"
|
||||
|
||||
@file_store_1 = packages_package_files.create!(file_store: 1, file_name: 'foo_1', file: 'foo_1', package_id: package.id)
|
||||
@file_store_2 = packages_package_files.create!(file_store: 2, file_name: 'foo_2', file: 'foo_2', package_id: package.id)
|
||||
@file_store_nil = packages_package_files.create!(file_store: nil, file_name: 'foo_nil', file: 'foo_nil', package_id: package.id)
|
||||
|
||||
# revert DB structure
|
||||
ActiveRecord::Base.connection.execute "ALTER TABLE packages_package_files ADD CONSTRAINT #{constraint_name} CHECK ((file_store IS NOT NULL)) NOT VALID"
|
||||
end
|
||||
|
||||
it 'correctly migrates nil file_store to 1' do
|
||||
migrate!
|
||||
|
||||
@file_store_1.reload
|
||||
@file_store_2.reload
|
||||
@file_store_nil.reload
|
||||
|
||||
expect(@file_store_1.file_store).to eq(1) # unchanged
|
||||
expect(@file_store_2.file_store).to eq(2) # unchanged
|
||||
expect(@file_store_nil.file_store).to eq(1) # nil => 1
|
||||
end
|
||||
end
|
|
@ -21,7 +21,7 @@ RSpec.describe Avatarable do
|
|||
it 'validates the file size' do
|
||||
expect(validator).to receive(:validate_each).and_call_original
|
||||
|
||||
project.update(avatar: 'uploads/avatar.png')
|
||||
project.update!(avatar: 'uploads/avatar.png')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -29,7 +29,7 @@ RSpec.describe Avatarable do
|
|||
it 'skips validation of file size' do
|
||||
expect(validator).not_to receive(:validate_each)
|
||||
|
||||
project.update(name: 'Hello world')
|
||||
project.update!(name: 'Hello world')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -187,7 +187,7 @@ RSpec.describe BulkInsertableAssociations do
|
|||
it 'invalidates the parent and returns false' do
|
||||
build_invalid_items(parent: parent)
|
||||
|
||||
expect(save_with_bulk_inserts(parent, bangify: false)).to be false
|
||||
expect(BulkInsertableAssociations.with_bulk_insert { parent.save }).to be false # rubocop:disable Rails/SaveBang
|
||||
expect(parent.errors[:bulk_foos].size).to eq(1)
|
||||
|
||||
expect(BulkFoo.count).to eq(0)
|
||||
|
@ -211,8 +211,8 @@ RSpec.describe BulkInsertableAssociations do
|
|||
|
||||
private
|
||||
|
||||
def save_with_bulk_inserts(entity, bangify: true)
|
||||
BulkInsertableAssociations.with_bulk_insert { bangify ? entity.save! : entity.save }
|
||||
def save_with_bulk_inserts(entity)
|
||||
BulkInsertableAssociations.with_bulk_insert { entity.save! }
|
||||
end
|
||||
|
||||
def build_items(parent:, relation: :bulk_foos, count: 10)
|
||||
|
|
|
@ -285,7 +285,7 @@ RSpec.describe CacheMarkdownField, :clean_gitlab_redis_cache do
|
|||
it_behaves_like 'a class with cached markdown fields'
|
||||
|
||||
describe '#attribute_invalidated?' do
|
||||
let(:thing) { klass.create(description: markdown, description_html: html, cached_markdown_version: cache_version) }
|
||||
let(:thing) { klass.create!(description: markdown, description_html: html, cached_markdown_version: cache_version) }
|
||||
|
||||
it 'returns true when cached_markdown_version is different' do
|
||||
thing.cached_markdown_version += 1
|
||||
|
@ -318,7 +318,7 @@ RSpec.describe CacheMarkdownField, :clean_gitlab_redis_cache do
|
|||
let(:thing) do
|
||||
# This forces the record to have outdated HTML. We can't use `create` because the `before_create` hook
|
||||
# would re-render the HTML to the latest version
|
||||
klass.create.tap do |thing|
|
||||
klass.create!.tap do |thing|
|
||||
thing.update_columns(description: markdown, description_html: old_html, cached_markdown_version: old_version)
|
||||
end
|
||||
end
|
||||
|
@ -326,7 +326,7 @@ RSpec.describe CacheMarkdownField, :clean_gitlab_redis_cache do
|
|||
it 'correctly updates cached HTML even if refresh_markdown_cache is called before updating the attribute' do
|
||||
thing.refresh_markdown_cache
|
||||
|
||||
thing.update(description: updated_markdown)
|
||||
thing.update!(description: updated_markdown)
|
||||
|
||||
expect(thing.description_html).to eq(updated_html)
|
||||
end
|
||||
|
|
|
@ -12,8 +12,8 @@ RSpec.describe CaseSensitivity do
|
|||
end
|
||||
end
|
||||
|
||||
let!(:model_1) { model.create(path: 'mOdEl-1', name: 'mOdEl 1') }
|
||||
let!(:model_2) { model.create(path: 'mOdEl-2', name: 'mOdEl 2') }
|
||||
let!(:model_1) { model.create!(path: 'mOdEl-1', name: 'mOdEl 1') }
|
||||
let!(:model_2) { model.create!(path: 'mOdEl-2', name: 'mOdEl 2') }
|
||||
|
||||
it 'finds a single instance by a single attribute regardless of case' do
|
||||
expect(model.iwhere(path: 'MODEL-1')).to contain_exactly(model_1)
|
||||
|
|
|
@ -180,6 +180,6 @@ RSpec.describe Featurable do
|
|||
|
||||
def update_all_project_features(project, features, value)
|
||||
project_feature_attributes = features.map { |f| ["#{f}_access_level", value] }.to_h
|
||||
project.project_feature.update(project_feature_attributes)
|
||||
project.project_feature.update!(project_feature_attributes)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -69,7 +69,7 @@ RSpec.describe Issuable do
|
|||
|
||||
it 'returns nil when author is nil' do
|
||||
issue.author_id = nil
|
||||
issue.save(validate: false)
|
||||
issue.save!(validate: false)
|
||||
|
||||
expect(issue.author_name).to eq nil
|
||||
end
|
||||
|
@ -361,13 +361,13 @@ RSpec.describe Issuable do
|
|||
end
|
||||
|
||||
it 'returns true when a subcription exists and subscribed is true' do
|
||||
issue.subscriptions.create(user: user, project: project, subscribed: true)
|
||||
issue.subscriptions.create!(user: user, project: project, subscribed: true)
|
||||
|
||||
expect(issue.subscribed?(user, project)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false when a subcription exists and subscribed is false' do
|
||||
issue.subscriptions.create(user: user, project: project, subscribed: false)
|
||||
issue.subscriptions.create!(user: user, project: project, subscribed: false)
|
||||
|
||||
expect(issue.subscribed?(user, project)).to be_falsey
|
||||
end
|
||||
|
@ -383,13 +383,13 @@ RSpec.describe Issuable do
|
|||
end
|
||||
|
||||
it 'returns true when a subcription exists and subscribed is true' do
|
||||
issue.subscriptions.create(user: user, project: project, subscribed: true)
|
||||
issue.subscriptions.create!(user: user, project: project, subscribed: true)
|
||||
|
||||
expect(issue.subscribed?(user, project)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false when a subcription exists and subscribed is false' do
|
||||
issue.subscriptions.create(user: user, project: project, subscribed: false)
|
||||
issue.subscriptions.create!(user: user, project: project, subscribed: false)
|
||||
|
||||
expect(issue.subscribed?(user, project)).to be_falsey
|
||||
end
|
||||
|
@ -437,7 +437,7 @@ RSpec.describe Issuable do
|
|||
let(:labels) { create_list(:label, 2) }
|
||||
|
||||
before do
|
||||
issue.update(labels: [labels[1]])
|
||||
issue.update!(labels: [labels[1]])
|
||||
expect(Gitlab::HookData::IssuableBuilder)
|
||||
.to receive(:new).with(issue).and_return(builder)
|
||||
end
|
||||
|
@ -456,7 +456,7 @@ RSpec.describe Issuable do
|
|||
context 'total_time_spent is updated' do
|
||||
before do
|
||||
issue.spend_time(duration: 2, user_id: user.id, spent_at: Time.current)
|
||||
issue.save
|
||||
issue.save!
|
||||
expect(Gitlab::HookData::IssuableBuilder)
|
||||
.to receive(:new).with(issue).and_return(builder)
|
||||
end
|
||||
|
@ -497,8 +497,8 @@ RSpec.describe Issuable do
|
|||
let(:user2) { create(:user) }
|
||||
|
||||
before do
|
||||
merge_request.update(assignees: [user])
|
||||
merge_request.update(assignees: [user, user2])
|
||||
merge_request.update!(assignees: [user])
|
||||
merge_request.update!(assignees: [user, user2])
|
||||
expect(Gitlab::HookData::IssuableBuilder)
|
||||
.to receive(:new).with(merge_request).and_return(builder)
|
||||
end
|
||||
|
@ -554,7 +554,7 @@ RSpec.describe Issuable do
|
|||
before do
|
||||
label_link = issue.label_links.find_by(label_id: second_label.id)
|
||||
label_link.label_id = nil
|
||||
label_link.save(validate: false)
|
||||
label_link.save!(validate: false)
|
||||
end
|
||||
|
||||
it 'filters out bad labels' do
|
||||
|
|
|
@ -177,7 +177,7 @@ RSpec.describe Issue, "Mentionable" do
|
|||
|
||||
expect(SystemNoteService).not_to receive(:cross_reference)
|
||||
|
||||
issue.update(description: 'New description')
|
||||
issue.update!(description: 'New description')
|
||||
issue.create_new_cross_references!
|
||||
end
|
||||
|
||||
|
@ -186,7 +186,7 @@ RSpec.describe Issue, "Mentionable" do
|
|||
|
||||
expect(SystemNoteService).to receive(:cross_reference).with(issues[1], any_args)
|
||||
|
||||
issue.update(description: issues[1].to_reference)
|
||||
issue.update!(description: issues[1].to_reference)
|
||||
issue.create_new_cross_references!
|
||||
end
|
||||
|
||||
|
@ -196,7 +196,7 @@ RSpec.describe Issue, "Mentionable" do
|
|||
|
||||
expect(SystemNoteService).to receive(:cross_reference).with(issues[1], any_args)
|
||||
|
||||
note.update(note: issues[1].to_reference)
|
||||
note.update!(note: issues[1].to_reference)
|
||||
note.create_new_cross_references!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -61,7 +61,7 @@ RSpec.describe Milestoneable do
|
|||
|
||||
it 'returns true with a milestone from the the parent of the issue project group' do
|
||||
parent = create(:group)
|
||||
group.update(parent: parent)
|
||||
group.update!(parent: parent)
|
||||
milestone = create(:milestone, group: parent)
|
||||
|
||||
expect(build_milestoneable(milestone.id).milestone_available?).to be_truthy
|
||||
|
|
|
@ -102,7 +102,7 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
|
||||
with_them do
|
||||
before do
|
||||
project.update(visibility_level: project_visibility_levels[visibility])
|
||||
project.update!(visibility_level: project_visibility_levels[visibility])
|
||||
end
|
||||
|
||||
it 'returns the proper participants' do
|
||||
|
@ -139,7 +139,7 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
|
||||
with_them do
|
||||
before do
|
||||
project.update(visibility_level: project_visibility_levels[visibility])
|
||||
project.update!(visibility_level: project_visibility_levels[visibility])
|
||||
end
|
||||
|
||||
it 'returns the proper participants' do
|
||||
|
@ -171,7 +171,7 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
|
||||
context 'when project is private' do
|
||||
before do
|
||||
project.update(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
|
||||
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
|
||||
end
|
||||
|
||||
it 'does not return any merge request for a non member' do
|
||||
|
@ -195,7 +195,7 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
|
||||
context 'when merge requests are available to project members' do
|
||||
before do
|
||||
project.project_feature.update(merge_requests_access_level: ProjectFeature::PRIVATE)
|
||||
project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
|
||||
end
|
||||
|
||||
it 'does not return any merge request for a non member' do
|
||||
|
|
|
@ -22,7 +22,7 @@ RSpec.describe Group, 'Routable' do
|
|||
end
|
||||
|
||||
it 'updates route record on path change' do
|
||||
group.update(path: 'wow', name: 'much')
|
||||
group.update!(path: 'wow', name: 'much')
|
||||
|
||||
expect(group.route.path).to eq('wow')
|
||||
expect(group.route.name).to eq('much')
|
||||
|
|
|
@ -20,13 +20,13 @@ RSpec.describe Subscribable, 'Subscribable' do
|
|||
end
|
||||
|
||||
it 'returns true when a subcription exists and subscribed is true' do
|
||||
resource.subscriptions.create(user: user_1, subscribed: true)
|
||||
resource.subscriptions.create!(user: user_1, subscribed: true)
|
||||
|
||||
expect(resource.subscribed?(user_1)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false when a subcription exists and subscribed is false' do
|
||||
resource.subscriptions.create(user: user_1, subscribed: false)
|
||||
resource.subscriptions.create!(user: user_1, subscribed: false)
|
||||
|
||||
expect(resource.subscribed?(user_1)).to be_falsey
|
||||
end
|
||||
|
@ -38,13 +38,13 @@ RSpec.describe Subscribable, 'Subscribable' do
|
|||
end
|
||||
|
||||
it 'returns true when a subcription exists and subscribed is true' do
|
||||
resource.subscriptions.create(user: user_1, project: project, subscribed: true)
|
||||
resource.subscriptions.create!(user: user_1, project: project, subscribed: true)
|
||||
|
||||
expect(resource.subscribed?(user_1, project)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false when a subcription exists and subscribed is false' do
|
||||
resource.subscriptions.create(user: user_1, project: project, subscribed: false)
|
||||
resource.subscriptions.create!(user: user_1, project: project, subscribed: false)
|
||||
|
||||
expect(resource.subscribed?(user_1, project)).to be_falsey
|
||||
end
|
||||
|
@ -58,9 +58,9 @@ RSpec.describe Subscribable, 'Subscribable' do
|
|||
|
||||
it 'returns the subscribed users' do
|
||||
user_2 = create(:user)
|
||||
resource.subscriptions.create(user: user_1, subscribed: true)
|
||||
resource.subscriptions.create(user: user_2, project: project, subscribed: true)
|
||||
resource.subscriptions.create(user: create(:user), project: project, subscribed: false)
|
||||
resource.subscriptions.create!(user: user_1, subscribed: true)
|
||||
resource.subscriptions.create!(user: user_2, project: project, subscribed: true)
|
||||
resource.subscriptions.create!(user: create(:user), project: project, subscribed: false)
|
||||
|
||||
expect(resource.subscribers(project)).to contain_exactly(user_1, user_2)
|
||||
end
|
||||
|
@ -113,7 +113,7 @@ RSpec.describe Subscribable, 'Subscribable' do
|
|||
describe '#unsubscribe' do
|
||||
context 'without project' do
|
||||
it 'unsubscribes the given current user' do
|
||||
resource.subscriptions.create(user: user_1, subscribed: true)
|
||||
resource.subscriptions.create!(user: user_1, subscribed: true)
|
||||
expect(resource.subscribed?(user_1)).to be_truthy
|
||||
|
||||
resource.unsubscribe(user_1)
|
||||
|
@ -124,7 +124,7 @@ RSpec.describe Subscribable, 'Subscribable' do
|
|||
|
||||
context 'with project' do
|
||||
it 'unsubscribes the given current user' do
|
||||
resource.subscriptions.create(user: user_1, project: project, subscribed: true)
|
||||
resource.subscriptions.create!(user: user_1, project: project, subscribed: true)
|
||||
expect(resource.subscribed?(user_1, project)).to be_truthy
|
||||
|
||||
resource.unsubscribe(user_1, project)
|
||||
|
@ -139,7 +139,7 @@ RSpec.describe Subscribable, 'Subscribable' do
|
|||
context 'when desired_state is set to true' do
|
||||
context 'when a user is subscribed to the resource' do
|
||||
it 'keeps the user subscribed' do
|
||||
resource.subscriptions.create(user: user_1, subscribed: true, project: resource_project)
|
||||
resource.subscriptions.create!(user: user_1, subscribed: true, project: resource_project)
|
||||
|
||||
resource.set_subscription(user_1, true, resource_project)
|
||||
|
||||
|
@ -159,7 +159,7 @@ RSpec.describe Subscribable, 'Subscribable' do
|
|||
context 'when desired_state is set to false' do
|
||||
context 'when a user is subscribed to the resource' do
|
||||
it 'unsubscribes the user from the resource' do
|
||||
resource.subscriptions.create(user: user_1, subscribed: true, project: resource_project)
|
||||
resource.subscriptions.create!(user: user_1, subscribed: true, project: resource_project)
|
||||
|
||||
expect { resource.set_subscription(user_1, false, resource_project) }
|
||||
.to change { resource.subscribed?(user_1, resource_project) }
|
||||
|
|
|
@ -137,7 +137,7 @@ RSpec.describe PersonalAccessToken, 'TokenAuthenticatable' do
|
|||
subject { PersonalAccessToken.find_by_token(token_value) }
|
||||
|
||||
it 'finds the token' do
|
||||
personal_access_token.save
|
||||
personal_access_token.save!
|
||||
|
||||
expect(subject).to eq(personal_access_token)
|
||||
end
|
||||
|
|
|
@ -750,7 +750,7 @@ RSpec.describe API::Files do
|
|||
|
||||
it "updates existing file in project repo with accepts correct last commit id" do
|
||||
last_commit = Gitlab::Git::Commit
|
||||
.last_for_path(project.repository, 'master', URI.unescape(file_path))
|
||||
.last_for_path(project.repository, 'master', Addressable::URI.unencode_component(file_path))
|
||||
params_with_correct_id = params.merge(last_commit_id: last_commit.id)
|
||||
|
||||
put api(route(file_path), user), params: params_with_correct_id
|
||||
|
@ -760,7 +760,7 @@ RSpec.describe API::Files do
|
|||
|
||||
it "returns 400 when file path is invalid" do
|
||||
last_commit = Gitlab::Git::Commit
|
||||
.last_for_path(project.repository, 'master', URI.unescape(file_path))
|
||||
.last_for_path(project.repository, 'master', Addressable::URI.unencode_component(file_path))
|
||||
params_with_correct_id = params.merge(last_commit_id: last_commit.id)
|
||||
|
||||
put api(route(rouge_file_path), user), params: params_with_correct_id
|
||||
|
@ -772,7 +772,7 @@ RSpec.describe API::Files do
|
|||
it_behaves_like 'when path is absolute' do
|
||||
let(:last_commit) do
|
||||
Gitlab::Git::Commit
|
||||
.last_for_path(project.repository, 'master', URI.unescape(file_path))
|
||||
.last_for_path(project.repository, 'master', Addressable::URI.unencode_component(file_path))
|
||||
end
|
||||
|
||||
let(:params_with_correct_id) { params.merge(last_commit_id: last_commit.id) }
|
||||
|
|
2
vendor/Dockerfile/Golang-alpine.Dockerfile
vendored
2
vendor/Dockerfile/Golang-alpine.Dockerfile
vendored
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.8-alpine AS builder
|
||||
FROM golang:1.15-alpine AS builder
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
|
2
vendor/Dockerfile/Golang-scratch.Dockerfile
vendored
2
vendor/Dockerfile/Golang-scratch.Dockerfile
vendored
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.8-alpine AS builder
|
||||
FROM golang:1.15-alpine AS builder
|
||||
|
||||
# We'll likely need to add SSL root certificates
|
||||
RUN apk --no-cache add ca-certificates
|
||||
|
|
2
vendor/Dockerfile/Golang.Dockerfile
vendored
2
vendor/Dockerfile/Golang.Dockerfile
vendored
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.8 AS builder
|
||||
FROM golang:1.15 AS builder
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
|
Loading…
Reference in a new issue