Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4ce0bee95d
commit
85e494935a
|
@ -1,3 +1,38 @@
|
|||
# Make sure to update all the similar conditions in other CI config files if you modify these conditions
|
||||
.if-default: &if-default
|
||||
if: '$CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ || $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/ || $CI_COMMIT_REF_NAME =~ /^security\// || $CI_MERGE_REQUEST_IID || $CI_COMMIT_TAG'
|
||||
|
||||
# Make sure to update all the similar conditions in other CI config files if you modify these conditions
|
||||
.if-default-ee: &if-default-ee
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ || $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/ || $CI_COMMIT_REF_NAME =~ /^security\// || $CI_MERGE_REQUEST_IID || $CI_COMMIT_TAG) && $CI_PROJECT_NAME =~ /^gitlab(-ee)?$/'
|
||||
|
||||
# Make sure to update all the similar conditions in other CI config files if you modify these conditions
|
||||
.if-master: &if-master
|
||||
if: '$CI_COMMIT_REF_NAME == "master"'
|
||||
|
||||
# Make sure to update all the similar patterns in other CI config files if you modify these patterns
|
||||
.code-backstage-patterns: &code-backstage-patterns
|
||||
- ".gitlab/ci/**/*"
|
||||
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
|
||||
- ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
|
||||
- ".csscomb.json"
|
||||
- "Dockerfile.assets"
|
||||
- "*_VERSION"
|
||||
- "Gemfile{,.lock}"
|
||||
- "Rakefile"
|
||||
- "{babel.config,jest.config}.js"
|
||||
- "config.ru"
|
||||
- "{package.json,yarn.lock}"
|
||||
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
|
||||
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
|
||||
# Backstage changes
|
||||
- "Dangerfile"
|
||||
- "danger/**/*"
|
||||
- "{,ee/}fixtures/**/*"
|
||||
- "{,ee/}rubocop/**/*"
|
||||
- "{,ee/}spec/**/*"
|
||||
- "doc/README.md" # Some RSpec test rely on this file
|
||||
|
||||
.assets-compile-cache:
|
||||
cache:
|
||||
paths:
|
||||
|
@ -132,7 +167,6 @@ compile-assets pull-cache foss:
|
|||
- .use-pg9
|
||||
stage: test
|
||||
needs: ["setup-test-env", "compile-assets pull-cache"]
|
||||
dependencies: ["setup-test-env", "compile-assets pull-cache"]
|
||||
|
||||
.karma-base:
|
||||
extends: .only-code-frontend-job-base
|
||||
|
@ -204,9 +238,10 @@ jest-foss:
|
|||
- .default-tags
|
||||
- .default-retry
|
||||
- .default-cache
|
||||
- .default-only
|
||||
- .only:changes-code-backstage
|
||||
stage: test
|
||||
rules:
|
||||
- <<: *if-master
|
||||
when: on_success
|
||||
dependencies: []
|
||||
cache:
|
||||
key: "$CI_JOB_NAME"
|
||||
|
@ -237,11 +272,12 @@ webpack-dev-server:
|
|||
- .default-tags
|
||||
- .default-retry
|
||||
- .default-cache
|
||||
- .default-only
|
||||
- .only:changes-code-backstage
|
||||
stage: test
|
||||
rules:
|
||||
- <<: *if-default
|
||||
changes: *code-backstage-patterns
|
||||
when: on_success
|
||||
needs: ["setup-test-env", "compile-assets pull-cache"]
|
||||
dependencies: ["setup-test-env", "compile-assets pull-cache"]
|
||||
variables:
|
||||
WEBPACK_MEMORY_TEST: "true"
|
||||
WEBPACK_VENDOR_DLL: "true"
|
||||
|
|
|
@ -5,7 +5,7 @@ Please describe the proposal and add a link to the source (for example, http://w
|
|||
-->
|
||||
|
||||
- [ ] Mention the proposal in the next backend weekly call and the #backend channel to encourage contribution
|
||||
- [ ] Proceed with the proposal once 50% of the maintainers have weighed in, and 80% of the votes are :+1:
|
||||
- [ ] Proceed with the proposal once 50% of the maintainers have weighed in, and 80% of their votes are :+1:
|
||||
- [ ] Once approved, mention it again in the next backend weekly call and the #backend channel
|
||||
|
||||
|
||||
|
|
4
Gemfile
4
Gemfile
|
@ -283,7 +283,7 @@ gem 'rack-proxy', '~> 0.6.0'
|
|||
gem 'sassc-rails', '~> 2.1.0'
|
||||
gem 'uglifier', '~> 2.7.2'
|
||||
|
||||
gem 'addressable', '~> 2.5.2'
|
||||
gem 'addressable', '~> 2.7'
|
||||
gem 'font-awesome-rails', '~> 4.7'
|
||||
gem 'gemojione', '~> 3.3'
|
||||
gem 'gon', '~> 6.2'
|
||||
|
@ -419,7 +419,7 @@ group :test do
|
|||
gem 'guard-rspec'
|
||||
end
|
||||
|
||||
gem 'octokit', '~> 4.9'
|
||||
gem 'octokit', '~> 4.15'
|
||||
|
||||
gem 'mail_room', '~> 0.10.0'
|
||||
|
||||
|
|
19
Gemfile.lock
19
Gemfile.lock
|
@ -55,8 +55,8 @@ GEM
|
|||
adamantium (0.2.0)
|
||||
ice_nine (~> 0.11.0)
|
||||
memoizable (~> 0.4.0)
|
||||
addressable (2.5.2)
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
aes_key_wrap (1.0.1)
|
||||
akismet (3.0.0)
|
||||
apollo_upload_server (2.0.0.beta.3)
|
||||
|
@ -650,7 +650,8 @@ GEM
|
|||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
octokit (4.9.0)
|
||||
octokit (4.15.0)
|
||||
faraday (>= 0.9)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
omniauth (1.9.0)
|
||||
hashie (>= 3.4.6, < 3.7.0)
|
||||
|
@ -762,7 +763,7 @@ GEM
|
|||
pry (~> 0.10)
|
||||
pry-rails (0.3.6)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (3.1.1)
|
||||
public_suffix (4.0.3)
|
||||
pyu-ruby-sasl (0.0.3.3)
|
||||
raabro (1.1.6)
|
||||
rack (2.0.7)
|
||||
|
@ -961,9 +962,9 @@ GEM
|
|||
sprockets (> 3.0)
|
||||
sprockets-rails
|
||||
tilt
|
||||
sawyer (0.8.1)
|
||||
addressable (>= 2.3.5, < 2.6)
|
||||
faraday (~> 0.8, < 1.0)
|
||||
sawyer (0.8.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (> 0.8, < 2.0)
|
||||
scss_lint (0.56.0)
|
||||
rake (>= 0.9, < 13)
|
||||
sass (~> 3.5.3)
|
||||
|
@ -1130,7 +1131,7 @@ DEPENDENCIES
|
|||
acme-client (~> 2.0.2)
|
||||
activerecord-explain-analyze (~> 0.1)
|
||||
acts-as-taggable-on (~> 6.0)
|
||||
addressable (~> 2.5.2)
|
||||
addressable (~> 2.7)
|
||||
akismet (~> 3.0)
|
||||
apollo_upload_server (~> 2.0.0.beta3)
|
||||
asana (~> 0.9)
|
||||
|
@ -1272,7 +1273,7 @@ DEPENDENCIES
|
|||
net-ssh (~> 5.2)
|
||||
nokogiri (~> 1.10.5)
|
||||
oauth2 (~> 1.4)
|
||||
octokit (~> 4.9)
|
||||
octokit (~> 4.15)
|
||||
omniauth (~> 1.8)
|
||||
omniauth-auth0 (~> 2.0.0)
|
||||
omniauth-authentiq (~> 0.3.3)
|
||||
|
|
|
@ -90,7 +90,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<div class="info-well d-none d-sm-flex project-last-commit commit p-3">
|
||||
<gl-loading-icon v-if="isLoading" size="md" class="m-auto" />
|
||||
<gl-loading-icon v-if="isLoading" size="md" color="dark" class="m-auto" />
|
||||
<template v-else>
|
||||
<user-avatar-link
|
||||
v-if="commit.author"
|
||||
|
|
|
@ -44,7 +44,7 @@ export default {
|
|||
</div>
|
||||
</div>
|
||||
<div class="blob-viewer">
|
||||
<gl-loading-icon v-if="loading > 0" size="md" class="my-4 mx-auto" />
|
||||
<gl-loading-icon v-if="loading > 0" size="md" color="dark" class="my-4 mx-auto" />
|
||||
<div v-else-if="readme" v-html="readme.html"></div>
|
||||
</div>
|
||||
</article>
|
||||
|
|
|
@ -34,6 +34,11 @@ export default {
|
|||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
loadingPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -69,7 +74,12 @@ export default {
|
|||
<table :aria-label="tableCaption" class="table tree-table qa-file-tree" aria-live="polite">
|
||||
<table-header v-once />
|
||||
<tbody>
|
||||
<parent-row v-show="showParentRow" :commit-ref="ref" :path="path" />
|
||||
<parent-row
|
||||
v-show="showParentRow"
|
||||
:commit-ref="ref"
|
||||
:path="path"
|
||||
:loading-path="loadingPath"
|
||||
/>
|
||||
<template v-for="val in entries">
|
||||
<table-row
|
||||
v-for="entry in val"
|
||||
|
@ -84,6 +94,7 @@ export default {
|
|||
:url="entry.webUrl"
|
||||
:submodule-tree-url="entry.treeUrl"
|
||||
:lfs-oid="entry.lfsOid"
|
||||
:loading-path="loadingPath"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="isLoading">
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<script>
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlLoadingIcon,
|
||||
},
|
||||
props: {
|
||||
commitRef: {
|
||||
type: String,
|
||||
|
@ -9,13 +14,21 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
loadingPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
parentRoute() {
|
||||
parentPath() {
|
||||
const splitArray = this.path.split('/');
|
||||
splitArray.pop();
|
||||
|
||||
return { path: `/tree/${this.commitRef}/${splitArray.join('/')}` };
|
||||
return splitArray.join('/');
|
||||
},
|
||||
parentRoute() {
|
||||
return { path: `/tree/${this.commitRef}/${this.parentPath}` };
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
@ -29,7 +42,13 @@ export default {
|
|||
<template>
|
||||
<tr class="tree-item">
|
||||
<td colspan="3" class="tree-item-file-name" @click.self="clickRow">
|
||||
<router-link :to="parentRoute" :aria-label="__('Go to parent')">
|
||||
<gl-loading-icon
|
||||
v-if="parentPath === loadingPath"
|
||||
size="sm"
|
||||
inline
|
||||
class="d-inline-block align-text-bottom"
|
||||
/>
|
||||
<router-link v-else :to="parentRoute" :aria-label="__('Go to parent')">
|
||||
..
|
||||
</router-link>
|
||||
</td>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { GlBadge, GlLink, GlSkeletonLoading, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { GlBadge, GlLink, GlSkeletonLoading, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
|
@ -12,6 +12,7 @@ export default {
|
|||
GlBadge,
|
||||
GlLink,
|
||||
GlSkeletonLoading,
|
||||
GlLoadingIcon,
|
||||
TimeagoTooltip,
|
||||
Icon,
|
||||
},
|
||||
|
@ -76,6 +77,11 @@ export default {
|
|||
required: false,
|
||||
default: null,
|
||||
},
|
||||
loadingPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -125,7 +131,13 @@ export default {
|
|||
<template>
|
||||
<tr :class="`file_${id}`" class="tree-item" @click="openRow">
|
||||
<td class="tree-item-file-name">
|
||||
<i :aria-label="type" role="img" :class="iconName" class="fa fa-fw"></i>
|
||||
<gl-loading-icon
|
||||
v-if="path === loadingPath"
|
||||
size="sm"
|
||||
inline
|
||||
class="d-inline-block align-text-bottom fa-fw"
|
||||
/>
|
||||
<i v-else :aria-label="type" role="img" :class="iconName" class="fa fa-fw"></i>
|
||||
<component :is="linkComponent" :to="routerLinkTo" :href="url" class="str-truncated">
|
||||
{{ fullPath }}
|
||||
</component>
|
||||
|
|
|
@ -27,6 +27,11 @@ export default {
|
|||
required: false,
|
||||
default: '/',
|
||||
},
|
||||
loadingPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -109,7 +114,12 @@ export default {
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<file-table :path="path" :entries="entries" :is-loading="isLoadingFiles" />
|
||||
<file-table
|
||||
:path="path"
|
||||
:entries="entries"
|
||||
:is-loading="isLoadingFiles"
|
||||
:loading-path="loadingPath"
|
||||
/>
|
||||
<file-preview v-if="readme" :blob="readme" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import getFiles from '../queries/getFiles.query.graphql';
|
||||
import getRefMixin from './get_ref';
|
||||
import getProjectPath from '../queries/getProjectPath.query.graphql';
|
||||
|
||||
export default {
|
||||
mixins: [getRefMixin],
|
||||
apollo: {
|
||||
projectPath: {
|
||||
query: getProjectPath,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return { projectPath: '', loadingPath: null };
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
this.preload(to.params.pathMatch, next);
|
||||
},
|
||||
methods: {
|
||||
preload(path, next) {
|
||||
this.loadingPath = path.replace(/^\//, '');
|
||||
|
||||
return this.$apollo
|
||||
.query({
|
||||
query: getFiles,
|
||||
variables: {
|
||||
projectPath: this.projectPath,
|
||||
ref: this.ref,
|
||||
path: this.loadingPath,
|
||||
nextPageCursor: '',
|
||||
pageSize: 100,
|
||||
},
|
||||
})
|
||||
.then(() => next());
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,11 +1,13 @@
|
|||
<script>
|
||||
import TreeContent from '../components/tree_content.vue';
|
||||
import { updateElementsVisibility } from '../utils/dom';
|
||||
import preloadMixin from '../mixins/preload';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TreeContent,
|
||||
},
|
||||
mixins: [preloadMixin],
|
||||
props: {
|
||||
path: {
|
||||
type: String,
|
||||
|
@ -34,5 +36,5 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<tree-content :path="path" />
|
||||
<tree-content :path="path" :loading-path="loadingPath" />
|
||||
</template>
|
||||
|
|
|
@ -39,6 +39,10 @@ class Projects::WikisController < Projects::ApplicationController
|
|||
if @page
|
||||
set_encoding_error unless valid_encoding?
|
||||
|
||||
# Assign vars expected by MarkupHelper
|
||||
@ref = params[:version_id]
|
||||
@path = @page.path
|
||||
|
||||
render 'show'
|
||||
elsif file_blob
|
||||
send_blob(@project_wiki.repository, file_blob)
|
||||
|
|
|
@ -132,6 +132,7 @@ module MarkupHelper
|
|||
pipeline: :wiki,
|
||||
project: @project,
|
||||
project_wiki: @project_wiki,
|
||||
repository: @project_wiki.repository,
|
||||
page_slug: wiki_page.slug,
|
||||
issuable_state_filter_enabled: true
|
||||
)
|
||||
|
|
|
@ -26,7 +26,7 @@ module Ci
|
|||
belongs_to :merge_request, class_name: 'MergeRequest'
|
||||
belongs_to :external_pull_request
|
||||
|
||||
has_internal_id :iid, scope: :project, presence: false, ensure_if: -> { !importing? }, init: ->(s) do
|
||||
has_internal_id :iid, scope: :project, presence: false, track_if: -> { !importing? }, ensure_if: -> { !importing? }, init: ->(s) do
|
||||
s&.project&.all_pipelines&.maximum(:iid) || s&.project&.all_pipelines&.count
|
||||
end
|
||||
|
||||
|
|
|
@ -27,13 +27,13 @@ module AtomicInternalId
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
class_methods do
|
||||
def has_internal_id(column, scope:, init:, ensure_if: nil, presence: true) # rubocop:disable Naming/PredicateName
|
||||
def has_internal_id(column, scope:, init:, ensure_if: nil, track_if: nil, presence: true) # rubocop:disable Naming/PredicateName
|
||||
# We require init here to retain the ability to recalculate in the absence of a
|
||||
# InternaLId record (we may delete records in `internal_ids` for example).
|
||||
# InternalId record (we may delete records in `internal_ids` for example).
|
||||
raise "has_internal_id requires a init block, none given." unless init
|
||||
raise "has_internal_id needs to be defined on association." unless self.reflect_on_association(scope)
|
||||
|
||||
before_validation :"track_#{scope}_#{column}!", on: :create
|
||||
before_validation :"track_#{scope}_#{column}!", on: :create, if: track_if
|
||||
before_validation :"ensure_#{scope}_#{column}!", on: :create, if: ensure_if
|
||||
validates column, presence: presence
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ class Deployment < ApplicationRecord
|
|||
include IidRoutes
|
||||
include AfterCommitQueue
|
||||
include UpdatedAtFilterable
|
||||
include Importable
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
belongs_to :project, required: true
|
||||
|
@ -17,7 +18,7 @@ class Deployment < ApplicationRecord
|
|||
has_many :merge_requests,
|
||||
through: :deployment_merge_requests
|
||||
|
||||
has_internal_id :iid, scope: :project, init: ->(s) do
|
||||
has_internal_id :iid, scope: :project, track_if: -> { !importing? }, init: ->(s) do
|
||||
Deployment.where(project: s.project).maximum(:iid) if s&.project
|
||||
end
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class Issue < ApplicationRecord
|
|||
belongs_to :duplicated_to, class_name: 'Issue'
|
||||
belongs_to :closed_by, class_name: 'User'
|
||||
|
||||
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.issues&.maximum(:iid) }
|
||||
has_internal_id :iid, scope: :project, track_if: -> { !importing? }, init: ->(s) { s&.project&.issues&.maximum(:iid) }
|
||||
|
||||
has_many :issue_milestones
|
||||
has_many :milestones, through: :issue_milestones
|
||||
|
@ -78,8 +78,8 @@ class Issue < ApplicationRecord
|
|||
|
||||
ignore_column :state, remove_with: '12.7', remove_after: '2019-12-22'
|
||||
|
||||
after_commit :expire_etag_cache
|
||||
after_save :ensure_metrics, unless: :imported?
|
||||
after_commit :expire_etag_cache, unless: :importing?
|
||||
after_save :ensure_metrics, unless: :importing?
|
||||
|
||||
attr_spammable :title, spam_title: true
|
||||
attr_spammable :description, spam_description: true
|
||||
|
|
|
@ -31,7 +31,7 @@ class MergeRequest < ApplicationRecord
|
|||
belongs_to :source_project, class_name: "Project"
|
||||
belongs_to :merge_user, class_name: "User"
|
||||
|
||||
has_internal_id :iid, scope: :target_project, init: ->(s) { s&.target_project&.merge_requests&.maximum(:iid) }
|
||||
has_internal_id :iid, scope: :target_project, track_if: -> { !importing? }, init: ->(s) { s&.target_project&.merge_requests&.maximum(:iid) }
|
||||
|
||||
has_many :merge_request_diffs
|
||||
|
||||
|
@ -97,8 +97,8 @@ class MergeRequest < ApplicationRecord
|
|||
after_create :ensure_merge_request_diff
|
||||
after_update :clear_memoized_shas
|
||||
after_update :reload_diff_if_branch_changed
|
||||
after_save :ensure_metrics
|
||||
after_commit :expire_etag_cache
|
||||
after_save :ensure_metrics, unless: :importing?
|
||||
after_commit :expire_etag_cache, unless: :importing?
|
||||
|
||||
# When this attribute is true some MR validation is ignored
|
||||
# It allows us to close or modify broken merge requests
|
||||
|
|
|
@ -138,7 +138,7 @@ class MergeRequestDiff < ApplicationRecord
|
|||
# All diff information is collected from repository after object is created.
|
||||
# It allows you to override variables like head_commit_sha before getting diff.
|
||||
after_create :save_git_content, unless: :importing?
|
||||
after_create_commit :set_as_latest_diff
|
||||
after_create_commit :set_as_latest_diff, unless: :importing?
|
||||
|
||||
after_save :update_external_diff_store, if: -> { !importing? && saved_change_to_external_diff? }
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ class Milestone < ApplicationRecord
|
|||
include StripAttribute
|
||||
include Milestoneish
|
||||
include FromUnion
|
||||
include Importable
|
||||
include Gitlab::SQL::Pattern
|
||||
|
||||
prepend_if_ee('::EE::Milestone') # rubocop: disable Cop/InjectEnterpriseEditionModule
|
||||
|
@ -30,8 +31,8 @@ class Milestone < ApplicationRecord
|
|||
has_many :milestone_releases
|
||||
has_many :releases, through: :milestone_releases
|
||||
|
||||
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.milestones&.maximum(:iid) }
|
||||
has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.milestones&.maximum(:iid) }
|
||||
has_internal_id :iid, scope: :project, track_if: -> { !importing? }, init: ->(s) { s&.project&.milestones&.maximum(:iid) }
|
||||
has_internal_id :iid, scope: :group, track_if: -> { !importing? }, init: ->(s) { s&.group&.milestones&.maximum(:iid) }
|
||||
|
||||
has_many :issues
|
||||
has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
class Release < ApplicationRecord
|
||||
include Presentable
|
||||
include CacheMarkdownField
|
||||
include Importable
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
cache_markdown_field :description
|
||||
|
@ -33,8 +34,8 @@ class Release < ApplicationRecord
|
|||
|
||||
delegate :repository, to: :project
|
||||
|
||||
after_commit :create_evidence!, on: :create
|
||||
after_commit :notify_new_release, on: :create
|
||||
after_commit :create_evidence!, on: :create, unless: :importing?
|
||||
after_commit :notify_new_release, on: :create, unless: :importing?
|
||||
|
||||
MAX_NUMBER_TO_DISPLAY = 3
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class User < ApplicationRecord
|
|||
include WithUploads
|
||||
include OptionallySearch
|
||||
include FromUnion
|
||||
include BatchDestroyDependentAssociations
|
||||
|
||||
DEFAULT_NOTIFICATION_LEVEL = :participating
|
||||
|
||||
|
|
|
@ -56,6 +56,13 @@ module Users
|
|||
|
||||
MigrateToGhostUserService.new(user).execute unless options[:hard_delete]
|
||||
|
||||
if Feature.enabled?(:destroy_user_associations_in_batches)
|
||||
# Rails attempts to load all related records into memory before
|
||||
# destroying: https://github.com/rails/rails/issues/22510
|
||||
# This ensures we delete records in batches.
|
||||
user.destroy_dependent_associations_in_batches
|
||||
end
|
||||
|
||||
# Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
|
||||
user_data = user.destroy
|
||||
namespace.destroy
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix error in Wiki when rendering the AsciiDoc include directive
|
||||
merge_request: 22565
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: 'Fix Issue API: creating with manual IID returns conflict when IID already
|
||||
in use'
|
||||
merge_request: 22788
|
||||
author: Mara Sophie Grosch
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add comment_on_event_enabled to services API
|
||||
merge_request:
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add `importing?` to disable some callbacks
|
||||
merge_request:
|
||||
author:
|
||||
type: performance
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Upgrade octokit and its dependencies
|
||||
merge_request: 22946
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: 'Use IS08601.3 format for app level logging of timestamps'
|
||||
merge_request: 22793
|
||||
author:
|
||||
type: other
|
|
@ -32,7 +32,8 @@ Example response:
|
|||
"confidential_note_events": true,
|
||||
"pipeline_events": true,
|
||||
"wiki_page_events": true,
|
||||
"job_events": true
|
||||
"job_events": true,
|
||||
"comment_on_event_enabled": true
|
||||
}
|
||||
{
|
||||
"id": 76,
|
||||
|
@ -50,7 +51,8 @@ Example response:
|
|||
"confidential_note_events": true,
|
||||
"pipeline_events": true,
|
||||
"wiki_page_events": true,
|
||||
"job_events": true
|
||||
"job_events": true,
|
||||
"comment_on_event_enabled": true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -723,6 +725,7 @@ Parameters:
|
|||
| `jira_issue_transition_id` | string | no | The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column. By default, this ID is set to `2`. |
|
||||
| `commit_events` | boolean | false | Enable notifications for commit events |
|
||||
| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
|
||||
| `comment_on_event_enabled` | boolean | false | Enable comments inside Jira issues on each GitLab event (commit / merge request) |
|
||||
|
||||
### Delete Jira service
|
||||
|
||||
|
@ -761,6 +764,7 @@ Example response:
|
|||
"note_events": true,
|
||||
"job_events": true,
|
||||
"pipeline_events": true,
|
||||
"comment_on_event_enabled": false,
|
||||
"properties": {
|
||||
"token": "<your_access_token>"
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ Here are some examples of how messages would be handled by both the loggers.
|
|||
FancyMultiLogger.info("Information")
|
||||
|
||||
# UnstructuredLogger
|
||||
I, [2020-01-13T12:02:41.566219 #6652] INFO -- : Information
|
||||
I, [2020-01-13T18:48:49.201Z #5647] INFO -- : Information
|
||||
|
||||
# StructuredLogger
|
||||
{:severity=>"INFO", :time=>"2020-01-13T11:02:41.559Z", :correlation_id=>"b1701f7ecc4be4bcd4c2d123b214e65a", :message=>"Information"}
|
||||
|
@ -203,7 +203,7 @@ I, [2020-01-13T12:02:41.566219 #6652] INFO -- : Information
|
|||
FancyMultiLogger.info({:message=>"This is my message", :project_id=>123})
|
||||
|
||||
# UnstructuredLogger
|
||||
I, [2020-01-13T12:06:09.856766 #8049] INFO -- : {:message=>"This is my message", :project_id=>123}
|
||||
I, [2020-01-13T19:01:17.091Z #11056] INFO -- : {"message"=>"Message", "project_id"=>"123"}
|
||||
|
||||
# StructuredLogger
|
||||
{:severity=>"INFO", :time=>"2020-01-13T11:06:09.851Z", :correlation_id=>"d7e0886f096db9a8526a4f89da0e45f6", :message=>"This is my message", :project_id=>123}
|
||||
|
|
|
@ -38,14 +38,40 @@ GitLab is developed for Linux-based operating systems.
|
|||
It does **not** run on Microsoft Windows, and we have no plans to support it in the near future. For the latest development status view this [issue](https://gitlab.com/gitlab-org/gitlab/issues/22337).
|
||||
Please consider using a virtual machine to run GitLab.
|
||||
|
||||
## Ruby versions
|
||||
## Software requirements
|
||||
|
||||
GitLab requires Ruby (MRI) 2.6. Support for Ruby versions below 2.6 (2.4, 2.5) will stop with GitLab 12.2.
|
||||
### Ruby versions
|
||||
|
||||
You will have to use the standard MRI implementation of Ruby.
|
||||
We love [JRuby](https://www.jruby.org/) and [Rubinius](https://rubinius.com) but GitLab
|
||||
GitLab requires Ruby (MRI) 2.6. Beginning in GitLab 12.2, we no longer support Ruby 2.5 and lower.
|
||||
|
||||
You must use the standard MRI implementation of Ruby.
|
||||
We love [JRuby](https://www.jruby.org/) and [Rubinius](https://rubinius.com), but GitLab
|
||||
needs several Gems that have native extensions.
|
||||
|
||||
### Go versions
|
||||
|
||||
The minimum required Go version is 1.12.
|
||||
|
||||
### Git versions
|
||||
|
||||
GitLab 11.11 and higher only supports Git 2.21.x and newer, and
|
||||
[dropped support for older versions](https://gitlab.com/gitlab-org/gitlab-foss/issues/54255).
|
||||
|
||||
### Node.js versions
|
||||
|
||||
Beginning in GitLab 11.8, we only support Node.js 8.10.0 or higher, and dropped
|
||||
support for Node.js 6.
|
||||
|
||||
We recommend Node 12.x, as it is faster.
|
||||
|
||||
GitLab uses [webpack](https://webpack.js.org/) to compile frontend assets, which requires a minimum
|
||||
version of Node.js 8.10.0.
|
||||
|
||||
You can check which version you are running with `node -v`. If you are running
|
||||
a version older than `v8.10.0`, you need to update to a newer version. You
|
||||
can find instructions to install from community maintained packages or compile
|
||||
from source at the [Node.js website](https://nodejs.org/en/download).
|
||||
|
||||
## Hardware requirements
|
||||
|
||||
### Storage
|
||||
|
|
|
@ -82,24 +82,15 @@ Install Bundler:
|
|||
sudo gem install bundler --no-document --version '< 2'
|
||||
```
|
||||
|
||||
### 4. Update Node
|
||||
### 4. Update Node.js
|
||||
|
||||
NOTE: Beginning in GitLab 11.8, we only support node 8 or higher, and dropped
|
||||
support for node 6. Be sure to upgrade if necessary.
|
||||
NOTE: To check the minimum required Node.js version, see [Node.js versions](../install/requirements.md#nodejs-versions).
|
||||
|
||||
GitLab utilizes [webpack](https://webpack.js.org/) to compile frontend assets.
|
||||
This requires a minimum version of node v8.10.0.
|
||||
|
||||
You can check which version you are running with `node -v`. If you are running
|
||||
a version older than `v8.10.0` you will need to update to a newer version. You
|
||||
can find instructions to install from community maintained packages or compile
|
||||
from source at the nodejs.org website.
|
||||
|
||||
<https://nodejs.org/en/download/>
|
||||
|
||||
GitLab also requires the use of yarn `>= v1.10.0` to manage JavaScript
|
||||
GitLab also requires the use of Yarn `>= v1.10.0` to manage JavaScript
|
||||
dependencies.
|
||||
|
||||
In Debian or Ubuntu:
|
||||
|
||||
```bash
|
||||
curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
|
||||
|
@ -107,34 +98,33 @@ sudo apt-get update
|
|||
sudo apt-get install yarn
|
||||
```
|
||||
|
||||
More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
|
||||
More information can be found on the [Yarn website](https://yarnpkg.com/en/docs/install).
|
||||
|
||||
### 5. Update Go
|
||||
|
||||
NOTE: GitLab 11.4 and higher only supports Go 1.10.x and newer, and dropped support for Go
|
||||
1.9.x. Be sure to upgrade your installation if necessary.
|
||||
NOTE: To check the minimum required Go version, see [Go versions](../install/requirements.md#go-versions).
|
||||
|
||||
You can check which version you are running with `go version`.
|
||||
|
||||
Download and install Go:
|
||||
Download and install Go (for Linux, 64-bit):
|
||||
|
||||
```bash
|
||||
# Remove former Go installation folder
|
||||
sudo rm -rf /usr/local/go
|
||||
|
||||
curl --remote-name --progress https://dl.google.com/go/go1.11.10.linux-amd64.tar.gz
|
||||
echo 'aefaa228b68641e266d1f23f1d95dba33f17552ba132878b65bb798ffa37e6d0 go1.11.10.linux-amd64.tar.gz' | shasum -a256 -c - && \
|
||||
sudo tar -C /usr/local -xzf go1.11.10.linux-amd64.tar.gz
|
||||
curl --remote-name --progress https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz
|
||||
echo '512103d7ad296467814a6e3f635631bd35574cab3369a97a323c9a585ccaa569 go1.13.5.linux-amd64.tar.gz' | shasum -a256 -c - && \
|
||||
sudo tar -C /usr/local -xzf go1.13.5.linux-amd64.tar.gz
|
||||
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
|
||||
rm go1.11.10.linux-amd64.tar.gz
|
||||
rm go1.13.5.linux-amd64.tar.gz
|
||||
|
||||
```
|
||||
|
||||
### 6. Update Git
|
||||
|
||||
NOTE: **Note:**
|
||||
GitLab 11.11 and higher only supports Git 2.21.x and newer, and
|
||||
[dropped support for older versions](https://gitlab.com/gitlab-org/gitlab-foss/issues/54255).
|
||||
Be sure to upgrade your installation if necessary.
|
||||
NOTE: To check the minimum required Git version, see [Git versions](../install/requirements.md#git-versions).
|
||||
|
||||
In Debian or Ubuntu:
|
||||
|
||||
```bash
|
||||
# Make sure Git is version 2.21.0 or higher
|
||||
|
@ -254,9 +244,8 @@ sudo -u git -H make
|
|||
|
||||
#### New configuration options for `gitlab.yml`
|
||||
|
||||
There might be configuration options available for [`gitlab.yml`][yaml]. View
|
||||
them with the command below and apply them manually to your current
|
||||
`gitlab.yml`:
|
||||
There might be configuration options available for [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)).
|
||||
View them with the command below and apply them manually to your current `gitlab.yml`:
|
||||
|
||||
```sh
|
||||
cd /home/git/gitlab
|
||||
|
@ -282,7 +271,7 @@ If you are using Strict-Transport-Security in your installation to continue
|
|||
using it you must enable it in your NGINX configuration as GitLab application no
|
||||
longer handles setting it.
|
||||
|
||||
If you are using Apache instead of NGINX please see the updated [Apache templates].
|
||||
If you are using Apache instead of NGINX see the updated [Apache templates](https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache).
|
||||
Also note that because Apache does not support upstreams behind Unix sockets you
|
||||
will need to let GitLab Workhorse listen on a TCP port. You can do this
|
||||
via [`/etc/default/gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/init.d/gitlab.default.example#L38).
|
||||
|
@ -296,13 +285,13 @@ add the following line to `config/initializers/smtp_settings.rb`:
|
|||
ActionMailer::Base.delivery_method = :smtp
|
||||
```
|
||||
|
||||
See [smtp_settings.rb.sample] as an example.
|
||||
See [smtp_settings.rb.sample](https://gitlab.com/gitlab-org/gitlab/blob/master/config/initializers/smtp_settings.rb.sample#L13) as an example.
|
||||
|
||||
#### Init script
|
||||
|
||||
There might be new configuration options available for
|
||||
[`gitlab.default.example`][gl-example]. View them with the command below and
|
||||
apply them manually to your current `/etc/default/gitlab`:
|
||||
[`gitlab.default.example`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/init.d/gitlab.default.example).
|
||||
View them with the command below and apply them manually to your current `/etc/default/gitlab`:
|
||||
|
||||
```sh
|
||||
cd /home/git/gitlab
|
||||
|
@ -389,17 +378,19 @@ Example:
|
|||
Additional instructions here.
|
||||
-->
|
||||
|
||||
## Things went south? Revert to previous version
|
||||
## Troubleshooting
|
||||
|
||||
### 1. Revert the code to the previous version
|
||||
|
||||
To revert to a previous version, you'll need to following the upgrading guides
|
||||
for the previous version. If you upgraded to 11.8 and want to revert back to
|
||||
11.7, you'll need to follow the guides for upgrading from 11.6 to 11.7. You can
|
||||
To revert to a previous version, you need to follow the upgrading guides
|
||||
for the previous version.
|
||||
|
||||
For example, if you have upgraded to GitLab 12.6 and want to revert back to
|
||||
12.5, you need to follow the guides for upgrading from 12.4 to 12.5. You can
|
||||
use the version dropdown at the top of the page to select the right version.
|
||||
|
||||
When reverting, you should _not_ follow the database migration guides, as the
|
||||
backup is already migrated to the previous version.
|
||||
When reverting, you should **not** follow the database migration guides, as the
|
||||
backup has already been migrated to the previous version.
|
||||
|
||||
### 2. Restore from the backup
|
||||
|
||||
|
@ -409,9 +400,4 @@ cd /home/git/gitlab
|
|||
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
|
||||
```
|
||||
|
||||
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
|
||||
|
||||
[yaml]: https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example
|
||||
[gl-example]: https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/init.d/gitlab.default.example
|
||||
[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab/blob/master/config/initializers/smtp_settings.rb.sample#L13
|
||||
[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
|
||||
If you have more than one backup `*.tar` file, add `BACKUP=timestamp_of_backup` to the above.
|
||||
|
|
|
@ -464,6 +464,11 @@ chart is used to install this application with a
|
|||
[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/elastic_stack/values.yaml)
|
||||
file.
|
||||
|
||||
NOTE: **Note:**
|
||||
The chart will deploy 4 Elasticsearch nodes: 2 masters, 1 data and 1 client node,
|
||||
with resource requests totalling 0.1 CPU and 3GB RAM. Each data node requests 1.5GB of memory,
|
||||
which makes it incompatible with clusters of `f1-micro` and `g1-small` instance types.
|
||||
|
||||
## Install using GitLab CI (alpha)
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/20822) in GitLab 12.6.
|
||||
|
|
|
@ -1132,7 +1132,7 @@ module API
|
|||
expose :commit_events, :push_events, :issues_events, :confidential_issues_events
|
||||
expose :merge_requests_events, :tag_push_events, :note_events
|
||||
expose :confidential_note_events, :pipeline_events, :wiki_page_events
|
||||
expose :job_events
|
||||
expose :job_events, :comment_on_event_enabled
|
||||
end
|
||||
|
||||
class ProjectService < ProjectServiceBasic
|
||||
|
|
|
@ -220,18 +220,22 @@ module API
|
|||
|
||||
issue_params = convert_parameters_from_legacy_format(issue_params)
|
||||
|
||||
issue = ::Issues::CreateService.new(user_project,
|
||||
current_user,
|
||||
issue_params.merge(request: request, api: true)).execute
|
||||
begin
|
||||
issue = ::Issues::CreateService.new(user_project,
|
||||
current_user,
|
||||
issue_params.merge(request: request, api: true)).execute
|
||||
|
||||
if issue.spam?
|
||||
render_api_error!({ error: 'Spam detected' }, 400)
|
||||
end
|
||||
if issue.spam?
|
||||
render_api_error!({ error: 'Spam detected' }, 400)
|
||||
end
|
||||
|
||||
if issue.valid?
|
||||
present issue, with: Entities::Issue, current_user: current_user, project: user_project
|
||||
else
|
||||
render_validation_error!(issue)
|
||||
if issue.valid?
|
||||
present issue, with: Entities::Issue, current_user: current_user, project: user_project
|
||||
else
|
||||
render_validation_error!(issue)
|
||||
end
|
||||
rescue ::ActiveRecord::RecordNotUnique
|
||||
render_api_error!('Duplicated issue', 409)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def format_message(severity, timestamp, progname, msg)
|
||||
"#{timestamp.to_s(:long)}: #{msg}\n"
|
||||
"#{timestamp.utc.iso8601(3)}: #{msg}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ module Gitlab
|
|||
super(logger: Gitlab::AppLogger)
|
||||
|
||||
@context = context
|
||||
@repository = context[:project].try(:repository)
|
||||
@repository = context[:repository] || context[:project].try(:repository)
|
||||
|
||||
# Note: Asciidoctor calls #freeze on extensions, so we can't set new
|
||||
# instance variables after initialization.
|
||||
|
@ -111,7 +111,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def ref
|
||||
context[:ref] || context[:project].default_branch
|
||||
context[:ref] || repository&.root_ref
|
||||
end
|
||||
|
||||
def requested_path
|
||||
|
|
|
@ -189,7 +189,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def default_api_endpoint
|
||||
OmniAuth::Strategies::GitHub.default_options[:client_options][:site]
|
||||
OmniAuth::Strategies::GitHub.default_options[:client_options][:site] || ::Octokit::Default.api_endpoint
|
||||
end
|
||||
|
||||
def verify_ssl
|
||||
|
|
|
@ -60,6 +60,7 @@ module Gitlab
|
|||
diff.importing = true
|
||||
diff.save
|
||||
diff.save_git_content
|
||||
diff.set_as_latest_diff
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -80,7 +80,7 @@ module Gitlab
|
|||
if host.present? && api_version.present?
|
||||
"#{host}/api/#{api_version}"
|
||||
else
|
||||
github_options[:site]
|
||||
github_options[:site] || ::Octokit::Default.api_endpoint
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Sentry
|
||||
class ApiUrls
|
||||
def initialize(url_base)
|
||||
@uri = URI(url_base).freeze
|
||||
end
|
||||
|
||||
def issues_url
|
||||
with_path(File.join(@uri.path, '/issues/'))
|
||||
end
|
||||
|
||||
def issue_url(issue_id)
|
||||
with_path("/api/0/issues/#{escape(issue_id)}/")
|
||||
end
|
||||
|
||||
def projects_url
|
||||
with_path('/api/0/projects/')
|
||||
end
|
||||
|
||||
def issue_latest_event_url(issue_id)
|
||||
with_path("/api/0/issues/#{escape(issue_id)}/events/latest/")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_path(new_path)
|
||||
new_uri = @uri.dup
|
||||
# Sentry API returns 404 if there are extra slashes in the URL
|
||||
new_uri.path = new_path.squeeze('/')
|
||||
|
||||
new_uri
|
||||
end
|
||||
|
||||
def escape(param)
|
||||
CGI.escape(param.to_s)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -19,6 +19,10 @@ module Sentry
|
|||
|
||||
private
|
||||
|
||||
def api_urls
|
||||
@api_urls ||= Sentry::ApiUrls.new(@url)
|
||||
end
|
||||
|
||||
def handle_mapping_exceptions(&block)
|
||||
yield
|
||||
rescue KeyError => e
|
||||
|
|
|
@ -4,20 +4,13 @@ module Sentry
|
|||
class Client
|
||||
module Event
|
||||
def issue_latest_event(issue_id:)
|
||||
latest_event = http_get(issue_latest_event_api_url(issue_id))[:body]
|
||||
latest_event = http_get(api_urls.issue_latest_event_url(issue_id))[:body]
|
||||
|
||||
map_to_event(latest_event)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def issue_latest_event_api_url(issue_id)
|
||||
latest_event_url = URI(url)
|
||||
latest_event_url.path = "/api/0/issues/#{issue_id}/events/latest/"
|
||||
|
||||
latest_event_url
|
||||
end
|
||||
|
||||
def map_to_event(event)
|
||||
stack_trace = parse_stack_trace(event)
|
||||
|
||||
|
|
|
@ -35,14 +35,14 @@ module Sentry
|
|||
end
|
||||
|
||||
def update_issue(issue_id:, params:)
|
||||
http_put(issue_api_url(issue_id), params)[:body]
|
||||
http_put(api_urls.issue_url(issue_id), params)[:body]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_issues(**keyword_args)
|
||||
response = http_get(
|
||||
issues_api_url,
|
||||
api_urls.issues_url,
|
||||
query: list_issue_sentry_query(keyword_args)
|
||||
)
|
||||
|
||||
|
@ -72,21 +72,7 @@ module Sentry
|
|||
end
|
||||
|
||||
def get_issue(issue_id:)
|
||||
http_get(issue_api_url(issue_id))[:body]
|
||||
end
|
||||
|
||||
def issues_api_url
|
||||
issues_url = URI("#{url}/issues/")
|
||||
issues_url.path.squeeze!('/')
|
||||
|
||||
issues_url
|
||||
end
|
||||
|
||||
def issue_api_url(issue_id)
|
||||
issue_url = URI(url)
|
||||
issue_url.path = "/api/0/issues/#{CGI.escape(issue_id.to_s)}/"
|
||||
|
||||
issue_url
|
||||
http_get(api_urls.issue_url(issue_id))[:body]
|
||||
end
|
||||
|
||||
def parse_gitlab_issue(plugin_issues)
|
||||
|
|
|
@ -14,14 +14,7 @@ module Sentry
|
|||
private
|
||||
|
||||
def get_projects
|
||||
http_get(projects_api_url)[:body]
|
||||
end
|
||||
|
||||
def projects_api_url
|
||||
projects_url = URI(url)
|
||||
projects_url.path = '/api/0/projects/'
|
||||
|
||||
projects_url
|
||||
http_get(api_urls.projects_url)[:body]
|
||||
end
|
||||
|
||||
def map_to_projects(projects)
|
||||
|
|
|
@ -41,6 +41,11 @@ describe "User browses files" do
|
|||
|
||||
it "shows the `Browse Directory` link" do
|
||||
click_link("files")
|
||||
|
||||
page.within('.repo-breadcrumb') do
|
||||
expect(page).to have_link('files')
|
||||
end
|
||||
|
||||
click_link("History")
|
||||
|
||||
expect(page).to have_link("Browse Directory").and have_no_link("Browse Code")
|
||||
|
|
|
@ -19,7 +19,17 @@ describe 'Projects > Files > User browses LFS files' do
|
|||
|
||||
it 'is possible to see raw content of LFS pointer' do
|
||||
click_link 'files'
|
||||
|
||||
page.within('.repo-breadcrumb') do
|
||||
expect(page).to have_link('files')
|
||||
end
|
||||
|
||||
click_link 'lfs'
|
||||
|
||||
page.within('.repo-breadcrumb') do
|
||||
expect(page).to have_link('lfs')
|
||||
end
|
||||
|
||||
click_link 'lfs_object.iso'
|
||||
|
||||
expect(page).to have_content 'version https://git-lfs.github.com/spec/v1'
|
||||
|
@ -38,6 +48,11 @@ describe 'Projects > Files > User browses LFS files' do
|
|||
|
||||
it 'shows an LFS object' do
|
||||
click_link('files')
|
||||
|
||||
page.within('.repo-breadcrumb') do
|
||||
expect(page).to have_link('files')
|
||||
end
|
||||
|
||||
click_link('lfs')
|
||||
click_link('lfs_object.iso')
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'User views AsciiDoc page with includes', :js do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:wiki_content_selector) { '[data-qa-selector=wiki_page_content]' }
|
||||
let(:project) { create(:project, :public, :wiki_repo) }
|
||||
let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page')}
|
||||
let!(:wiki_page) { create_wiki_page('home', content: "Content from the main page.\ninclude::included_page.asciidoc[]") }
|
||||
|
||||
def create_wiki_page(title, content:)
|
||||
attrs = {
|
||||
title: title,
|
||||
content: content,
|
||||
format: :asciidoc
|
||||
}
|
||||
|
||||
create(:wiki_page, wiki: project.wiki, attrs: attrs)
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
context 'when the file being included exists' do
|
||||
it 'includes the file contents' do
|
||||
visit(project_wiki_path(project, wiki_page))
|
||||
|
||||
page.within(:css, wiki_content_selector) do
|
||||
expect(page).to have_content('Content from the main page. Content from the included page')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are multiple versions of the wiki pages' do
|
||||
before do
|
||||
included_wiki_page.update(message: 'updated included file', content: 'Updated content from the included page')
|
||||
wiki_page.update(message: 'updated wiki page', content: "Updated content from the main page.\ninclude::included_page.asciidoc[]")
|
||||
end
|
||||
|
||||
let(:latest_version_id) { wiki_page.versions.first.id }
|
||||
let(:oldest_version_id) { wiki_page.versions.last.id }
|
||||
|
||||
context 'viewing the latest version' do
|
||||
it 'includes the latest content' do
|
||||
visit(project_wiki_path(project, wiki_page, version_id: latest_version_id))
|
||||
|
||||
page.within(:css, wiki_content_selector) do
|
||||
expect(page).to have_content('Updated content from the main page. Updated content from the included page')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'viewing the original version' do
|
||||
it 'includes the content from the original version' do
|
||||
visit(project_wiki_path(project, wiki_page, version_id: oldest_version_id))
|
||||
|
||||
page.within(:css, wiki_content_selector) do
|
||||
expect(page).to have_content('Content from the main page. Content from the included page')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the file being included does not exist' do
|
||||
before do
|
||||
included_wiki_page.delete
|
||||
end
|
||||
|
||||
it 'outputs an error' do
|
||||
visit(project_wiki_path(project, wiki_page))
|
||||
|
||||
page.within(:css, wiki_content_selector) do
|
||||
expect(page).to have_content('Content from the main page. [ERROR: include::included_page.asciidoc[] - unresolved directive]')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,7 +16,8 @@
|
|||
"confidential_note_events": { "type": "boolean" },
|
||||
"pipeline_events": { "type": "boolean" },
|
||||
"wiki_page_events": { "type": "boolean" },
|
||||
"job_events": { "type": "boolean" }
|
||||
"job_events": { "type": "boolean" },
|
||||
"comment_on_event_enabled": { "type": "boolean" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import ParentRow from '~/repository/components/table/parent_row.vue';
|
||||
|
||||
let vm;
|
||||
let $router;
|
||||
|
||||
function factory(path) {
|
||||
function factory(path, loadingPath) {
|
||||
$router = {
|
||||
push: jest.fn(),
|
||||
};
|
||||
|
@ -13,6 +14,7 @@ function factory(path) {
|
|||
propsData: {
|
||||
commitRef: 'master',
|
||||
path,
|
||||
loadingPath,
|
||||
},
|
||||
stubs: {
|
||||
RouterLink: RouterLinkStub,
|
||||
|
@ -61,4 +63,10 @@ describe('Repository parent row component', () => {
|
|||
path: '/tree/master/app',
|
||||
});
|
||||
});
|
||||
|
||||
it('renders loading icon when loading parent', () => {
|
||||
factory('app/assets', 'app');
|
||||
|
||||
expect(vm.find(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
|
||||
import { GlBadge, GlLink } from '@gitlab/ui';
|
||||
import { GlBadge, GlLink, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
import TableRow from '~/repository/components/table/row.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
|
@ -198,4 +198,17 @@ describe('Repository table row component', () => {
|
|||
expect(vm.find(Icon).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders loading icon when path is loading', () => {
|
||||
factory({
|
||||
id: '1',
|
||||
sha: '1',
|
||||
path: 'test',
|
||||
type: 'tree',
|
||||
currentPath: '/',
|
||||
loadingPath: 'test',
|
||||
});
|
||||
|
||||
expect(vm.find(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -273,16 +273,19 @@ describe MarkupHelper do
|
|||
|
||||
describe '#render_wiki_content' do
|
||||
let(:wiki) { double('WikiPage', path: "file.#{extension}") }
|
||||
let(:wiki_repository) { double('Repository') }
|
||||
let(:context) do
|
||||
{
|
||||
pipeline: :wiki, project: project, project_wiki: wiki,
|
||||
page_slug: 'nested/page', issuable_state_filter_enabled: true
|
||||
page_slug: 'nested/page', issuable_state_filter_enabled: true,
|
||||
repository: wiki_repository
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
expect(wiki).to receive(:content).and_return('wiki content')
|
||||
expect(wiki).to receive(:slug).and_return('nested/page')
|
||||
expect(wiki).to receive(:repository).and_return(wiki_repository)
|
||||
helper.instance_variable_set(:@project_wiki, wiki)
|
||||
end
|
||||
|
||||
|
|
|
@ -15,4 +15,11 @@ describe Gitlab::AppTextLogger do
|
|||
it 'logs a string unchanged' do
|
||||
expect(subject.format_message('INFO', Time.now, nil, string_message)).to include(string_message)
|
||||
end
|
||||
|
||||
it 'logs time in UTC with ISO8601.3 standard' do
|
||||
Timecop.freeze do
|
||||
expect(subject.format_message('INFO', Time.now, nil, string_message))
|
||||
.to include(Time.now.utc.iso8601(3))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -518,6 +518,28 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
context 'when repository is passed into the context' do
|
||||
let(:wiki_repo) { project.wiki.repository }
|
||||
let(:include_path) { 'wiki_file.adoc' }
|
||||
|
||||
before do
|
||||
project.create_wiki
|
||||
context.merge!(repository: wiki_repo)
|
||||
end
|
||||
|
||||
context 'when the file exists' do
|
||||
before do
|
||||
create_file(include_path, 'Content from wiki', repository: wiki_repo)
|
||||
end
|
||||
|
||||
it { is_expected.to include('<p>Content from wiki</p>') }
|
||||
end
|
||||
|
||||
context 'when the file does not exist' do
|
||||
it { is_expected.to include("[ERROR: include::#{include_path}[] - unresolved directive]")}
|
||||
end
|
||||
end
|
||||
|
||||
context 'recursive includes with relative paths' do
|
||||
let(:input) do
|
||||
<<~ADOC
|
||||
|
@ -562,8 +584,8 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def create_file(path, content)
|
||||
project.repository.create_file(project.creator, path, content,
|
||||
def create_file(path, content, repository: project.repository)
|
||||
repository.create_file(project.creator, path, content,
|
||||
message: "Add #{path}", branch_name: 'asciidoc')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Sentry::ApiUrls do
|
||||
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project/' }
|
||||
let(:token) { 'test-token' }
|
||||
let(:issue_id) { '123456' }
|
||||
let(:issue_id_with_reserved_chars) { '123$%' }
|
||||
let(:escaped_issue_id) { '123%24%25' }
|
||||
let(:api_urls) { Sentry::ApiUrls.new(sentry_url) }
|
||||
|
||||
# Sentry API returns 404 if there are extra slashes in the URL!
|
||||
shared_examples 'correct url with extra slashes' do
|
||||
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects//sentry-org/sentry-project/' }
|
||||
|
||||
it_behaves_like 'correct url'
|
||||
end
|
||||
|
||||
shared_examples 'correctly escapes issue ID' do
|
||||
context 'with param a string with reserved chars' do
|
||||
let(:issue_id) { issue_id_with_reserved_chars }
|
||||
|
||||
it { expect(subject.to_s).to include(escaped_issue_id) }
|
||||
end
|
||||
|
||||
context 'with param a symbol with reserved chars' do
|
||||
let(:issue_id) { issue_id_with_reserved_chars.to_sym }
|
||||
|
||||
it { expect(subject.to_s).to include(escaped_issue_id) }
|
||||
end
|
||||
|
||||
context 'with param an integer' do
|
||||
let(:issue_id) { 12345678 }
|
||||
|
||||
it { expect(subject.to_s).to include(issue_id.to_s) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#issues_url' do
|
||||
subject { api_urls.issues_url }
|
||||
|
||||
shared_examples 'correct url' do
|
||||
it { is_expected.to eq_uri('https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project/issues/') }
|
||||
end
|
||||
|
||||
it_behaves_like 'correct url'
|
||||
it_behaves_like 'correct url with extra slashes'
|
||||
end
|
||||
|
||||
describe '#issue_url' do
|
||||
subject { api_urls.issue_url(issue_id) }
|
||||
|
||||
shared_examples 'correct url' do
|
||||
it { is_expected.to eq_uri("https://sentrytest.gitlab.com/api/0/issues/#{issue_id}/") }
|
||||
end
|
||||
|
||||
it_behaves_like 'correct url'
|
||||
it_behaves_like 'correct url with extra slashes'
|
||||
it_behaves_like 'correctly escapes issue ID'
|
||||
end
|
||||
|
||||
describe '#projects_url' do
|
||||
subject { api_urls.projects_url }
|
||||
|
||||
shared_examples 'correct url' do
|
||||
it { is_expected.to eq_uri('https://sentrytest.gitlab.com/api/0/projects/') }
|
||||
end
|
||||
|
||||
it_behaves_like 'correct url'
|
||||
it_behaves_like 'correct url with extra slashes'
|
||||
end
|
||||
|
||||
describe '#issue_latest_event_url' do
|
||||
subject { api_urls.issue_latest_event_url(issue_id) }
|
||||
|
||||
shared_examples 'correct url' do
|
||||
it { is_expected.to eq_uri("https://sentrytest.gitlab.com/api/0/issues/#{issue_id}/events/latest/") }
|
||||
end
|
||||
|
||||
it_behaves_like 'correct url'
|
||||
it_behaves_like 'correct url with extra slashes'
|
||||
it_behaves_like 'correctly escapes issue ID'
|
||||
end
|
||||
end
|
|
@ -109,28 +109,6 @@ describe Sentry::Client::Issue do
|
|||
it_behaves_like 'no Sentry redirects'
|
||||
end
|
||||
|
||||
# Sentry API returns 404 if there are extra slashes in the URL!
|
||||
context 'extra slashes in URL' do
|
||||
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects//sentry-org/sentry-project/' }
|
||||
|
||||
let(:sentry_request_url) do
|
||||
'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project/' \
|
||||
'issues/?limit=20&query=is:unresolved'
|
||||
end
|
||||
|
||||
it 'removes extra slashes in api url' do
|
||||
expect(client.url).to eq(sentry_url)
|
||||
expect(Gitlab::HTTP).to receive(:get).with(
|
||||
URI('https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project/issues/'),
|
||||
anything
|
||||
).and_call_original
|
||||
|
||||
subject
|
||||
|
||||
expect(sentry_api_request).to have_been_requested
|
||||
end
|
||||
end
|
||||
|
||||
context 'requests with sort parameter in sentry api' do
|
||||
let(:sentry_request_url) do
|
||||
'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project/' \
|
||||
|
@ -232,14 +210,6 @@ describe Sentry::Client::Issue do
|
|||
|
||||
subject { client.issue_details(issue_id: issue_id) }
|
||||
|
||||
it 'escapes issue ID' do
|
||||
allow(CGI).to receive(:escape).and_call_original
|
||||
|
||||
subject
|
||||
|
||||
expect(CGI).to have_received(:escape).with(issue_id.to_s)
|
||||
end
|
||||
|
||||
context 'error object created from sentry response' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
|
|
|
@ -91,25 +91,6 @@ describe Sentry::Client::Projects do
|
|||
it_behaves_like 'no Sentry redirects'
|
||||
end
|
||||
|
||||
# Sentry API returns 404 if there are extra slashes in the URL!
|
||||
context 'extra slashes in URL' do
|
||||
let(:sentry_url) { 'https://sentrytest.gitlab.com/api//0/projects//' }
|
||||
let!(:valid_req_stub) do
|
||||
stub_sentry_request(sentry_list_projects_url)
|
||||
end
|
||||
|
||||
it 'removes extra slashes in api url' do
|
||||
expect(Gitlab::HTTP).to receive(:get).with(
|
||||
URI(sentry_list_projects_url),
|
||||
anything
|
||||
).and_call_original
|
||||
|
||||
subject
|
||||
|
||||
expect(valid_req_stub).to have_been_requested
|
||||
end
|
||||
end
|
||||
|
||||
context 'when exception is raised' do
|
||||
let(:sentry_request_url) { sentry_list_projects_url }
|
||||
|
||||
|
|
|
@ -9,6 +9,32 @@ describe AtomicInternalId do
|
|||
let(:scope_attrs) { { project: milestone.project } }
|
||||
let(:usage) { :milestones }
|
||||
|
||||
describe '#save!' do
|
||||
context 'when IID is provided' do
|
||||
before do
|
||||
milestone.iid = external_iid
|
||||
end
|
||||
|
||||
it 'tracks the value' do
|
||||
expect(milestone).to receive(:track_project_iid!)
|
||||
|
||||
milestone.save!
|
||||
end
|
||||
|
||||
context 'when importing' do
|
||||
before do
|
||||
milestone.importing = true
|
||||
end
|
||||
|
||||
it 'does not track the value' do
|
||||
expect(milestone).not_to receive(:track_project_iid!)
|
||||
|
||||
milestone.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#track_project_iid!' do
|
||||
subject { milestone.track_project_iid! }
|
||||
|
||||
|
|
|
@ -160,6 +160,16 @@ describe API::Issues do
|
|||
expect(json_response['iid']).not_to eq 9001
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an issue with the same IID exists on database' do
|
||||
it 'returns 409' do
|
||||
post api("/projects/#{project.id}/issues", admin),
|
||||
params: { title: 'new issue', iid: issue.iid }
|
||||
|
||||
expect(response).to have_gitlab_http_status(409)
|
||||
expect(json_response['message']).to eq 'Duplicated issue'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates a new project issue' do
|
||||
|
|
|
@ -20,6 +20,22 @@ describe Users::DestroyService do
|
|||
expect { Namespace.find(namespace.id) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
||||
it 'deletes user associations in batches' do
|
||||
expect(user).to receive(:destroy_dependent_associations_in_batches)
|
||||
|
||||
service.execute(user)
|
||||
end
|
||||
|
||||
context 'when :destroy_user_associations_in_batches flag is disabled' do
|
||||
it 'does not delete user associations in batches' do
|
||||
stub_feature_flags(destroy_user_associations_in_batches: false)
|
||||
|
||||
expect(user).not_to receive(:destroy_dependent_associations_in_batches)
|
||||
|
||||
service.execute(user)
|
||||
end
|
||||
end
|
||||
|
||||
it 'will delete the project' do
|
||||
expect_next_instance_of(Projects::DestroyService) do |destroy_service|
|
||||
expect(destroy_service).to receive(:execute).once.and_return(true)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Assert the result matches a URI object initialized with the expectation variable.
|
||||
#
|
||||
# Success:
|
||||
# ```
|
||||
# expect(URI('www.fish.com')).to eq_uri('www.fish.com')
|
||||
# ```
|
||||
#
|
||||
# Failure:
|
||||
# ```
|
||||
# expect(URI('www.fish.com')).to eq_uri('www.dog.com')
|
||||
# ```
|
||||
#
|
||||
RSpec::Matchers.define :eq_uri do |expected|
|
||||
match do |actual|
|
||||
actual == URI(expected)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue