Commit c2ef7635 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'master' into '41587-osw-mr-metrics-migration-take-two-ee'

Conflicts:
   lib/gitlab/import_export/relation_factory.rb
parents 7ffb8750 e333c3cf
...@@ -8,8 +8,6 @@ engines: ...@@ -8,8 +8,6 @@ engines:
languages: languages:
- ruby - ruby
- javascript - javascript
exclude_paths:
- "lib/api/v3/*"
ratings: ratings:
paths: paths:
- Gemfile.lock - Gemfile.lock
......
...@@ -6,7 +6,7 @@ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.7-golang-1.9-git ...@@ -6,7 +6,7 @@ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.7-golang-1.9-git
- gitlab-org - gitlab-org
.default-cache: &default-cache .default-cache: &default-cache
key: "ruby-2.3.7-with-yarn" key: "ruby-2.3.7-debian-stretch-with-yarn"
paths: paths:
- vendor/ruby - vendor/ruby
- .yarn-cache/ - .yarn-cache/
...@@ -701,7 +701,7 @@ static-analysis: ...@@ -701,7 +701,7 @@ static-analysis:
script: script:
- scripts/static-analysis - scripts/static-analysis
cache: cache:
key: "ruby-2.3.7-with-yarn-and-rubocop" key: "ruby-2.3.7-debian-stretch-with-yarn-and-rubocop"
paths: paths:
- vendor/ruby - vendor/ruby
- .yarn-cache/ - .yarn-cache/
...@@ -742,7 +742,7 @@ ee_compat_check: ...@@ -742,7 +742,7 @@ ee_compat_check:
except: except:
- master - master
- tags - tags
- /^[\d-]+-stable(-ee)?/ - /[\d-]+-stable(-ee)?/
- /^security-/ - /^security-/
- branches@gitlab-org/gitlab-ee - branches@gitlab-org/gitlab-ee
- branches@gitlab/gitlab-ee - branches@gitlab/gitlab-ee
......
...@@ -173,7 +173,6 @@ Lint/UriEscapeUnescape: ...@@ -173,7 +173,6 @@ Lint/UriEscapeUnescape:
- 'spec/requests/api/files_spec.rb' - 'spec/requests/api/files_spec.rb'
- 'spec/requests/api/internal_spec.rb' - 'spec/requests/api/internal_spec.rb'
- 'spec/requests/api/issues_spec.rb' - 'spec/requests/api/issues_spec.rb'
- 'spec/requests/api/v3/issues_spec.rb'
# Offense count: 1 # Offense count: 1
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
...@@ -333,8 +332,6 @@ RSpec/ScatteredSetup: ...@@ -333,8 +332,6 @@ RSpec/ScatteredSetup:
- 'spec/lib/gitlab/bitbucket_import/importer_spec.rb' - 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
- 'spec/lib/gitlab/git/env_spec.rb' - 'spec/lib/gitlab/git/env_spec.rb'
- 'spec/requests/api/jobs_spec.rb' - 'spec/requests/api/jobs_spec.rb'
- 'spec/requests/api/v3/builds_spec.rb'
- 'spec/requests/api/v3/projects_spec.rb'
- 'spec/services/projects/create_service_spec.rb' - 'spec/services/projects/create_service_spec.rb'
# Offense count: 1 # Offense count: 1
...@@ -618,7 +615,6 @@ Style/OrAssignment: ...@@ -618,7 +615,6 @@ Style/OrAssignment:
Exclude: Exclude:
- 'app/models/concerns/token_authenticatable.rb' - 'app/models/concerns/token_authenticatable.rb'
- 'lib/api/commit_statuses.rb' - 'lib/api/commit_statuses.rb'
- 'lib/api/v3/members.rb'
- 'lib/gitlab/project_transfer.rb' - 'lib/gitlab/project_transfer.rb'
# Offense count: 50 # Offense count: 50
...@@ -781,7 +777,6 @@ Style/TernaryParentheses: ...@@ -781,7 +777,6 @@ Style/TernaryParentheses:
- 'app/finders/projects_finder.rb' - 'app/finders/projects_finder.rb'
- 'app/helpers/namespaces_helper.rb' - 'app/helpers/namespaces_helper.rb'
- 'features/support/capybara.rb' - 'features/support/capybara.rb'
- 'lib/api/v3/projects.rb'
- 'lib/gitlab/ci/build/artifacts/metadata/entry.rb' - 'lib/gitlab/ci/build/artifacts/metadata/entry.rb'
- 'spec/requests/api/pipeline_schedules_spec.rb' - 'spec/requests/api/pipeline_schedules_spec.rb'
- 'spec/support/capybara.rb' - 'spec/support/capybara.rb'
......
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
## 10.8.3 (2018-05-30)
- No changes.
- No changes.
### Fixed (1 change)
- Geo - Calculate the wiki checksum even when wiki is disabled. !5772
### Performance (1 change)
- Make Geo::PruneEventLogWorker delete rows more gently. !5835
## 10.8.2 (2018-05-28) ## 10.8.2 (2018-05-28)
### Security (3 changes) ### Security (3 changes)
......
...@@ -2,6 +2,20 @@ ...@@ -2,6 +2,20 @@
documentation](doc/development/changelog.md) for instructions on adding your own documentation](doc/development/changelog.md) for instructions on adding your own
entry. entry.
## 10.8.3 (2018-05-30)
### Fixed (4 changes)
- Replace Gitlab::REVISION with Gitlab.revision and handle installations without a .git directory. !19125
- Fix encoding of branch names on compare and new merge request page. !19143
- Fix remote mirror database inconsistencies when upgrading from EE to CE. !19196
- Fix local storage not being cleared after creating a new issue.
### Performance (1 change)
- Memoize Gitlab::Database.version.
## 10.8.2 (2018-05-28) ## 10.8.2 (2018-05-28)
### Security (3 changes) ### Security (3 changes)
......
...@@ -143,7 +143,7 @@ gem 'gitlab-markup', '~> 1.6.2' ...@@ -143,7 +143,7 @@ gem 'gitlab-markup', '~> 1.6.2'
gem 'redcarpet', '~> 3.4' gem 'redcarpet', '~> 3.4'
gem 'commonmarker', '~> 0.17' gem 'commonmarker', '~> 0.17'
gem 'RedCloth', '~> 4.3.2' gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 4.2' gem 'rdoc', '~> 6.0'
gem 'org-ruby', '~> 0.9.12' gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0' gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1' gem 'wikicloth', '0.8.1'
...@@ -154,6 +154,9 @@ gem 'truncato', '~> 0.7.9' ...@@ -154,6 +154,9 @@ gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0' gem 'bootstrap_form', '~> 2.7.0'
gem 'nokogiri', '~> 1.8.2' gem 'nokogiri', '~> 1.8.2'
# Calendar rendering
gem 'icalendar'
# Diffs # Diffs
gem 'diffy', '~> 3.1.0' gem 'diffy', '~> 3.1.0'
...@@ -229,7 +232,7 @@ gem 'asana', '~> 0.6.0' ...@@ -229,7 +232,7 @@ gem 'asana', '~> 0.6.0'
gem 'ruby-fogbugz', '~> 0.2.1' gem 'ruby-fogbugz', '~> 0.2.1'
# Kubernetes integration # Kubernetes integration
gem 'kubeclient', '~> 3.0' gem 'kubeclient', '~> 3.1.0'
# Sanitize user input # Sanitize user input
gem 'sanitize', '~> 2.0' gem 'sanitize', '~> 2.0'
...@@ -332,7 +335,7 @@ group :development, :test do ...@@ -332,7 +335,7 @@ group :development, :test do
gem 'pry-byebug', '~> 3.4.1', platform: :mri gem 'pry-byebug', '~> 3.4.1', platform: :mri
gem 'pry-rails', '~> 0.3.4' gem 'pry-rails', '~> 0.3.4'
gem 'awesome_print', '~> 1.2.0', require: false gem 'awesome_print', require: false
gem 'fuubar', '~> 2.2.0' gem 'fuubar', '~> 2.2.0'
gem 'database_cleaner', '~> 1.5.0' gem 'database_cleaner', '~> 1.5.0'
......
...@@ -69,7 +69,7 @@ GEM ...@@ -69,7 +69,7 @@ GEM
attr_encrypted (3.1.0) attr_encrypted (3.1.0)
encryptor (~> 3.0.0) encryptor (~> 3.0.0)
attr_required (1.0.0) attr_required (1.0.0)
awesome_print (1.2.0) awesome_print (1.8.0)
aws-sdk (2.9.32) aws-sdk (2.9.32)
aws-sdk-resources (= 2.9.32) aws-sdk-resources (= 2.9.32)
aws-sdk-core (2.9.32) aws-sdk-core (2.9.32)
...@@ -176,7 +176,7 @@ GEM ...@@ -176,7 +176,7 @@ GEM
diff-lcs (1.3) diff-lcs (1.3)
diffy (3.1.0) diffy (3.1.0)
docile (1.1.5) docile (1.1.5)
domain_name (0.5.20170404) domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (4.3.2) doorkeeper (4.3.2)
railties (>= 4.2) railties (>= 4.2)
...@@ -437,6 +437,7 @@ GEM ...@@ -437,6 +437,7 @@ GEM
httpclient (2.8.3) httpclient (2.8.3)
i18n (0.9.5) i18n (0.9.5)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
icalendar (2.4.1)
ice_nine (0.11.2) ice_nine (0.11.2)
influxdb (0.2.3) influxdb (0.2.3)
cause cause
...@@ -474,9 +475,9 @@ GEM ...@@ -474,9 +475,9 @@ GEM
knapsack (1.16.0) knapsack (1.16.0)
rake rake
timecop (>= 0.1.0) timecop (>= 0.1.0)
kubeclient (3.0.0) kubeclient (3.1.0)
http (~> 2.2.2) http (~> 2.2.2)
recursive-open-struct (~> 1.0.4) recursive-open-struct (~> 1.0, >= 1.0.4)
rest-client (~> 2.0) rest-client (~> 2.0)
launchy (2.4.3) launchy (2.4.3)
addressable (~> 2.3) addressable (~> 2.3)
...@@ -723,12 +724,11 @@ GEM ...@@ -723,12 +724,11 @@ GEM
ffi ffi
rbnacl-libsodium (1.0.11) rbnacl-libsodium (1.0.11)
rbnacl (>= 3.0.1) rbnacl (>= 3.0.1)
rdoc (4.2.2) rdoc (6.0.4)
json (~> 1.4)
re2 (1.1.1) re2 (1.1.1)
recaptcha (3.0.0) recaptcha (3.0.0)
json json
recursive-open-struct (1.0.5) recursive-open-struct (1.1.0)
redcarpet (3.4.0) redcarpet (3.4.0)
redis (3.3.5) redis (3.3.5)
redis-actionpack (5.0.2) redis-actionpack (5.0.2)
...@@ -830,7 +830,7 @@ GEM ...@@ -830,7 +830,7 @@ GEM
rubyzip (1.2.1) rubyzip (1.2.1)
rufus-scheduler (3.4.0) rufus-scheduler (3.4.0)
et-orbi (~> 1.0) et-orbi (~> 1.0)
rugged (0.27.0) rugged (0.27.1)
safe_yaml (1.0.4) safe_yaml (1.0.4)
sanitize (2.1.0) sanitize (2.1.0)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
...@@ -1007,7 +1007,7 @@ DEPENDENCIES ...@@ -1007,7 +1007,7 @@ DEPENDENCIES
asciidoctor-plantuml (= 0.0.8) asciidoctor-plantuml (= 0.0.8)
asset_sync (~> 2.4) asset_sync (~> 2.4)
attr_encrypted (~> 3.1.0) attr_encrypted (~> 3.1.0)
awesome_print (~> 1.2.0) awesome_print
aws-sdk aws-sdk
babosa (~> 1.0.2) babosa (~> 1.0.2)
base32 (~> 0.3.0) base32 (~> 0.3.0)
...@@ -1097,6 +1097,7 @@ DEPENDENCIES ...@@ -1097,6 +1097,7 @@ DEPENDENCIES
html-pipeline (~> 2.7.1) html-pipeline (~> 2.7.1)
html2text html2text
httparty (~> 0.13.3) httparty (~> 0.13.3)
icalendar
influxdb (~> 0.2) influxdb (~> 0.2)
jira-ruby (~> 1.4) jira-ruby (~> 1.4)
jquery-atwho-rails (~> 1.3.2) jquery-atwho-rails (~> 1.3.2)
...@@ -1104,7 +1105,7 @@ DEPENDENCIES ...@@ -1104,7 +1105,7 @@ DEPENDENCIES
jwt (~> 1.5.6) jwt (~> 1.5.6)
kaminari (~> 1.0) kaminari (~> 1.0)
knapsack (~> 1.16) knapsack (~> 1.16)
kubeclient (~> 3.0) kubeclient (~> 3.1.0)
letter_opener_web (~> 1.3.0) letter_opener_web (~> 1.3.0)
license_finder (~> 3.1) license_finder (~> 3.1)
licensee (~> 8.9) licensee (~> 8.9)
...@@ -1161,7 +1162,7 @@ DEPENDENCIES ...@@ -1161,7 +1162,7 @@ DEPENDENCIES
rblineprof (~> 0.3.6) rblineprof (~> 0.3.6)
rbnacl (~> 4.0) rbnacl (~> 4.0)
rbnacl-libsodium rbnacl-libsodium
rdoc (~> 4.2) rdoc (~> 6.0)
re2 (~> 1.1.1) re2 (~> 1.1.1)
recaptcha (~> 3.0) recaptcha (~> 3.0)
redcarpet (~> 3.4) redcarpet (~> 3.4)
......
...@@ -41,10 +41,10 @@ gl.issueBoards.ModalEmptyState = Vue.extend({ ...@@ -41,10 +41,10 @@ gl.issueBoards.ModalEmptyState = Vue.extend({
template: ` template: `
<section class="empty-state"> <section class="empty-state">
<div class="row"> <div class="row">
<div class="col-xs-12 col-sm-6 order-sm-last"> <div class="col-12 col-md-6 order-md-last">
<aside class="svg-content"><img :src="emptyStateSvg"/></aside> <aside class="svg-content"><img :src="emptyStateSvg"/></aside>
</div> </div>
<div class="col-xs-12 col-sm-6 order-sm-first"> <div class="col-12 col-md-6 order-md-first">
<div class="text-content"> <div class="text-content">
<h4>{{ contents.title }}</h4> <h4>{{ contents.title }}</h4>
<p v-html="contents.content"></p> <p v-html="contents.content"></p>
......
...@@ -144,14 +144,14 @@ export default { ...@@ -144,14 +144,14 @@ export default {
<loading-button <loading-button
:loading="submitCommitLoading" :loading="submitCommitLoading"
:disabled="commitButtonDisabled" :disabled="commitButtonDisabled"
container-class="btn btn-success btn-sm pull-left" container-class="btn btn-success btn-sm float-left"
:label="__('Commit')" :label="__('Commit')"
@click="commitChanges" @click="commitChanges"
/> />
<button <button
v-if="!discardDraftButtonDisabled" v-if="!discardDraftButtonDisabled"
type="button" type="button"
class="btn btn-default btn-sm pull-right" class="btn btn-default btn-sm float-right"
@click="discardDraft" @click="discardDraft"
> >
{{ __('Discard draft') }} {{ __('Discard draft') }}
...@@ -159,7 +159,7 @@ export default { ...@@ -159,7 +159,7 @@ export default {
<button <button
v-else v-else
type="button" type="button"
class="btn btn-default btn-sm pull-right" class="btn btn-default btn-sm float-right"
@click="toggleIsSmall" @click="toggleIsSmall"
> >
{{ __('Collapse') }} {{ __('Collapse') }}
......
<script>
import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
Icon,
},
props: {
file: {
type: Object,
required: true,
},
},
computed: {
showButtons() {
return this.file.permalink;
},
},
};
</script>
<template>
<div
v-if="showButtons"
class="pull-right ide-btn-group"
>
<a
:href="file.permalink"
target="_blank"
:title="s__('IDE|Open in file view')"
rel="noopener noreferrer"
>
<span class="vertical-align-middle">Open in file view</span>
<icon
name="external-link"
css-classes="vertical-align-middle space-right"
:size="16"
/>
</a>
</div>
</template>
<script>
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
Icon,
},
directives: {
tooltip,
},
props: {
file: {
type: Object,
required: true,
},
},
computed: {
showButtons() {
return (
this.file.rawPath || this.file.blamePath || this.file.commitsPath || this.file.permalink
);
},
rawDownloadButtonLabel() {
return this.file.binary ? __('Download') : __('Raw');
},
},
};
</script>
<template>
<div
v-if="showButtons"
class="float-right ide-btn-group"
>
<a
v-tooltip
v-if="!file.binary"
:href="file.blamePath"
:title="__('Blame')"
class="btn btn-sm btn-transparent blame"
>
<icon
name="blame"
:size="16"
/>
</a>
<a
v-tooltip
:href="file.commitsPath"
:title="__('History')"
class="btn btn-sm btn-transparent history"
>
<icon
name="history"
:size="16"
/>
</a>
<a
v-tooltip
:href="file.permalink"
:title="__('Permalink')"
class="btn btn-sm btn-transparent permalink"
>
<icon
name="link"
:size="16"
/>
</a>
<a
v-tooltip
:href="file.rawPath"
target="_blank"
class="btn btn-sm btn-transparent prepend-left-10 raw"
rel="noopener noreferrer"
:title="rawDownloadButtonLabel">
<icon
name="download"
:size="16"
/>
</a>
</div>
</template>
...@@ -73,10 +73,9 @@ export default { ...@@ -73,10 +73,9 @@ export default {
<form <form
slot="body" slot="body"
@submit.prevent="createEntryInStore" @submit.prevent="createEntryInStore"
class="form-group row append-bottom-0" class="form-group row"
> >
<fieldset class="form-group append-bottom-0"> <label class="label-light col-form-label col-sm-3">
<label class="label-light col-form-label col-sm-3 ide-new-modal-label">
{{ __('Name') }} {{ __('Name') }}
</label> </label>
<div class="col-sm-9"> <div class="col-sm-9">
...@@ -87,7 +86,6 @@ export default { ...@@ -87,7 +86,6 @@ export default {
ref="fieldName" ref="fieldName"
/> />
</div> </div>
</fieldset>
</form> </form>
</deprecated-modal> </deprecated-modal>
</template> </template>
...@@ -6,12 +6,12 @@ import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer ...@@ -6,12 +6,12 @@ import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer
import { activityBarViews, viewerTypes } from '../constants'; import { activityBarViews, viewerTypes } from '../constants';
import monacoLoader from '../monaco_loader'; import monacoLoader from '../monaco_loader';
import Editor from '../lib/editor'; import Editor from '../lib/editor';
import IdeFileButtons from './ide_file_buttons.vue'; import ExternalLink from './external_link.vue';
export default { export default {
components: { components: {
ContentViewer, ContentViewer,
IdeFileButtons, ExternalLink,
}, },
props: { props: {
file: { file: {
...@@ -224,7 +224,7 @@ export default { ...@@ -224,7 +224,7 @@ export default {
</a> </a>
</li> </li>
</ul> </ul>
<ide-file-buttons <external-link
:file="file" :file="file"
/> />
</div> </div>
......
...@@ -32,7 +32,7 @@ export default class IssuableForm { ...@@ -32,7 +32,7 @@ export default class IssuableForm {
} }
this.initAutosave(); this.initAutosave();
this.form.on('submit:success', this.handleSubmit); this.form.on('submit', this.handleSubmit);
this.form.on('click', '.btn-cancel', this.resetAutosave); this.form.on('click', '.btn-cancel', this.resetAutosave);
this.initWip(); this.initWip();
......
...@@ -362,7 +362,7 @@ export default class MergeRequestTabs { ...@@ -362,7 +362,7 @@ export default class MergeRequestTabs {
// //
// status - Boolean, true to show, false to hide // status - Boolean, true to show, false to hide
toggleLoading(status) { toggleLoading(status) {
$('.mr-loading-status .loading').toggleClass('hidden', status); $('.mr-loading-status .loading').toggleClass('hidden', !status);
} }
diffViewType() { diffViewType() {
......
...@@ -77,8 +77,7 @@ export default class UserTabs { ...@@ -77,8 +77,7 @@ export default class UserTabs {
this.action = action || this.defaultAction; this.action = action || this.defaultAction;
this.$parentEl = $(parentEl) || $(document); this.$parentEl = $(parentEl) || $(document);
this.windowLocation = window.location; this.windowLocation = window.location;
this.$parentEl.find('.nav-links a') this.$parentEl.find('.nav-links a').each((i, navLink) => {
.each((i, navLink) => {
this.loaded[$(navLink).attr('data-action')] = false; this.loaded[$(navLink).attr('data-action')] = false;
}); });
this.actions = Object.keys(this.loaded); this.actions = Object.keys(this.loaded);
...@@ -116,8 +115,7 @@ export default class UserTabs { ...@@ -116,8 +115,7 @@ export default class UserTabs {
} }
activateTab(action) { activateTab(action) {
return this.$parentEl.find(`.nav-links .js-${action}-tab a`) return this.$parentEl.find(`.nav-links .js-${action}-tab a`).tab('show');
.tab('show');
} }
setTab(action, endpoint) { setTab(action, endpoint) {
...@@ -137,7 +135,8 @@ export default class UserTabs { ...@@ -137,7 +135,8 @@ export default class UserTabs {
loadTab(action, endpoint) { loadTab(action, endpoint) {
this.toggleLoading(true); this.toggleLoading(true);
return axios.get(endpoint) return axios
.get(endpoint)
.then(({ data }) => { .then(({ data }) => {
const tabSelector = `div#${action}`; const tabSelector = `div#${action}`;
this.$parentEl.find(tabSelector).html(data.html); this.$parentEl.find(tabSelector).html(data.html);
...@@ -161,10 +160,11 @@ export default class UserTabs { ...@@ -161,10 +160,11 @@ export default class UserTabs {
const utcOffset = $calendarWrap.data('utcOffset'); const utcOffset = $calendarWrap.data('utcOffset');
let utcFormatted = 'UTC'; let utcFormatted = 'UTC';
if (utcOffset !== 0) { if (utcOffset !== 0) {
utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${(utcOffset / 3600)}`; utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${utcOffset / 3600}`;
} }
axios.get(calendarPath) axios
.get(calendarPath)
.then(({ data }) => { .then(({ data }) => {
$calendarWrap.html(CALENDAR_TEMPLATE); $calendarWrap.html(CALENDAR_TEMPLATE);
$calendarWrap.find('.calendar-hint').append(`(Timezone: ${utcFormatted})`); $calendarWrap.find('.calendar-hint').append(`(Timezone: ${utcFormatted})`);
...@@ -180,17 +180,20 @@ export default class UserTabs { ...@@ -180,17 +180,20 @@ export default class UserTabs {
} }
toggleLoading(status) { toggleLoading(status) {
return this.$parentEl.find('.loading-status .loading') return this.$parentEl.find('.loading-status .loading').toggleClass('hidden', !status);
.toggleClass('hidden', status);
} }
setCurrentAction(source) { setCurrentAction(source) {
let newState = source; let newState = source;
newState = newState.replace(/\/+$/, ''); newState = newState.replace(/\/+$/, '');
newState += this.windowLocation.search + this.windowLocation.hash; newState += this.windowLocation.search + this.windowLocation.hash;
history.replaceState({ history.replaceState(
{
url: newState, url: newState,
}, document.title, newState); },
document.title,
newState,
);
return newState; return newState;
} }
......
...@@ -132,7 +132,7 @@ export default { ...@@ -132,7 +132,7 @@ export default {
</div> </div>
</div> </div>
<span <span
class="help-block" class="form-text text-muted"
:class="{ 'gl-field-error': hasErrors }" :class="{ 'gl-field-error': hasErrors }"
v-if="hasErrors" v-if="hasErrors"
> >
......
...@@ -193,7 +193,7 @@ export default { ...@@ -193,7 +193,7 @@ export default {
</div> </div>
</div> </div>
<span <span
class="help-block" class="form-text text-muted"
:class="{ 'gl-field-error': hasErrors }" :class="{ 'gl-field-error': hasErrors }"
v-html="helpText" v-html="helpText"
></span> ></span>
......
...@@ -106,7 +106,7 @@ export default { ...@@ -106,7 +106,7 @@ export default {
</div> </div>
</div> </div>
<span <span
class="help-block" class="form-text text-muted"
:class="{ 'gl-field-error': hasErrors }" :class="{ 'gl-field-error': hasErrors }"
v-if="hasErrors" v-if="hasErrors"
> >
......
...@@ -168,8 +168,8 @@ ...@@ -168,8 +168,8 @@
<a <a
:href="mr.mergeCommitPath" :href="mr.mergeCommitPath"
class="commit-sha js-mr-merged-commit-sha" class="commit-sha js-mr-merged-commit-sha"
v-text="mr.shortMergeCommitSha"
> >
{{ mr.shortMergeCommitSha }}
</a> </a>
<clipboard-button <clipboard-button
:title="__('Copy commit SHA to clipboard')" :title="__('Copy commit SHA to clipboard')"
......
...@@ -131,6 +131,10 @@ table { ...@@ -131,6 +131,10 @@ table {
} }
.card { .card {
.card-title {
margin-bottom: 0;
}
&.card-without-border { &.card-without-border {
@extend .border-0; @extend .border-0;
} }
...@@ -147,3 +151,7 @@ table { ...@@ -147,3 +151,7 @@ table {
.nav-tabs .nav-link { .nav-tabs .nav-link {
border: 0; border: 0;
} }
pre code {
white-space: pre-wrap;
}
...@@ -74,12 +74,6 @@ body.modal-open { ...@@ -74,12 +74,6 @@ body.modal-open {
} }
} }
@include media-breakpoint-up(lg) {
.modal-full {
width: 98%;
}
}
.modal { .modal {
background-color: $black-transparent; background-color: $black-transparent;
z-index: 2100; z-index: 2100;
......
...@@ -1088,10 +1088,6 @@ ...@@ -1088,10 +1088,6 @@
font-size: 12px; font-size: 12px;
} }
.ide-new-modal-label {
line-height: 34px;
}
.multi-file-commit-panel-success-message { .multi-file-commit-panel-success-message {
position: absolute; position: absolute;
top: 61px; top: 61px;
......
...@@ -17,10 +17,23 @@ module IssuesAction ...@@ -17,10 +17,23 @@ module IssuesAction
end end
# rubocop:enable Gitlab/ModuleWithInstanceVariables # rubocop:enable Gitlab/ModuleWithInstanceVariables
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def issues_calendar
@issues = issuables_collection
.non_archived
.with_due_date
.limit(100)
respond_to do |format|
format.ics { response.headers['Content-Disposition'] = 'inline' }
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
private private
def finder_type def finder_type
(super if defined?(super)) || (super if defined?(super)) ||
(IssuesFinder if action_name == 'issues') (IssuesFinder if %w(issues issues_calendar).include?(action_name))
end end
end end
module Groups
class SharedProjectsController < Groups::ApplicationController
respond_to :json
before_action :group
skip_cross_project_access_check :index
def index
shared_projects = GroupProjectsFinder.new(
group: group,
current_user: current_user,
params: finder_params,
options: { only_shared: true }
).execute
serializer = GroupChildSerializer.new(current_user: current_user)
.with_pagination(request, response)
render json: serializer.represent(shared_projects)
end
private
def finder_params
@finder_params ||= begin
# Make the `search` param consistent for the frontend,
# which will be using `filter`.
params[:search] ||= params[:filter] if params[:filter]
params.permit(:sort, :search)
end
end
end
end
...@@ -34,12 +34,12 @@ class ProfilesController < Profiles::ApplicationController ...@@ -34,12 +34,12 @@ class ProfilesController < Profiles::ApplicationController
redirect_to profile_personal_access_tokens_path redirect_to profile_personal_access_tokens_path
end end
def reset_rss_token def reset_feed_token
Users::UpdateService.new(current_user, user: @user).execute! do |user| Users::UpdateService.new(current_user, user: @user).execute! do |user|
user.reset_rss_token! user.reset_feed_token!
end end
flash[:notice] = "RSS token was successfully reset" flash[:notice] = "Feed token was successfully reset"
redirect_to profile_personal_access_tokens_path redirect_to profile_personal_access_tokens_path
end end
...@@ -93,8 +93,6 @@ class ProfilesController < Profiles::ApplicationController ...@@ -93,8 +93,6 @@ class ProfilesController < Profiles::ApplicationController
:linkedin, :linkedin,
:location, :location,
:name, :name,
:password,
:password_confirmation,
:public_email, :public_email,
:skype, :skype,
:twitter, :twitter,
......
...@@ -11,9 +11,9 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -11,9 +11,9 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :whitelist_query_limiting_ee, only: [:update] before_action :whitelist_query_limiting_ee, only: [:update]
before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update] before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update]
before_action :check_issues_available! before_action :check_issues_available!
before_action :issue, except: [:index, :new, :create, :bulk_update, :export_csv] before_action :issue, except: [:index, :calendar, :new, :create, :bulk_update, :export_csv]
before_action :set_issuables_index, only: [:index] before_action :set_issuables_index, only: [:index, :calendar]
# Allow write(create) issue # Allow write(create) issue
before_action :authorize_create_issue!, only: [:new, :create] before_action :authorize_create_issue!, only: [:new, :create]
...@@ -43,6 +43,17 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -43,6 +43,17 @@ class Projects::IssuesController < Projects::ApplicationController
end end
end end
def calendar
@issues = @issuables
.non_archived
.with_due_date
.limit(100)
respond_to do |format|
format.ics { response.headers['Content-Disposition'] = 'inline' }
end
end
def new def new
params[:issue] ||= ActionController::Parameters.new( params[:issue] ||= ActionController::Parameters.new(
assignee_ids: "" assignee_ids: ""
......
...@@ -306,14 +306,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -306,14 +306,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
elsif @merge_request.actual_head_pipeline.success? elsif @merge_request.actual_head_pipeline.success?
# This can be triggered when a user clicks the auto merge button while # This can be triggered when a user clicks the auto merge button while
# the tests finish at about the same time # the tests finish at about the same time
@merge_request.merge_async(current_user.id, params) @merge_request.merge_async(current_user.id, merge_params)
:success :success
else else
:failed :failed
end end
else else
@merge_request.merge_async(current_user.id, params) @merge_request.merge_async(current_user.id, merge_params)
:success :success
end end
......
...@@ -77,6 +77,8 @@ class IssuesFinder < IssuableFinder ...@@ -77,6 +77,8 @@ class IssuesFinder < IssuableFinder
items = items.due_between(Date.today.beginning_of_week, Date.today.end_of_week) items = items.due_between(Date.today.beginning_of_week, Date.today.end_of_week)
elsif filter_by_due_this_month? elsif filter_by_due_this_month?
items = items.due_between(Date.today.beginning_of_month, Date.today.end_of_month) items = items.due_between(Date.today.beginning_of_month, Date.today.end_of_month)
elsif filter_by_due_next_month_and_previous_two_weeks?
items = items.due_between(Date.today - 2.weeks, (Date.today + 1.month).end_of_month)
end end
end end
...@@ -99,6 +101,10 @@ class IssuesFinder < IssuableFinder ...@@ -99,6 +101,10 @@ class IssuesFinder < IssuableFinder
due_date? && params[:due_date] == Issue::DueThisMonth.name due_date? && params[:due_date] == Issue::DueThisMonth.name
end end
def filter_by_due_next_month_and_previous_two_weeks?
due_date? && params[:due_date] == Issue::DueNextMonthAndPreviousTwoWeeks.name
end
def due_date? def due_date?
params[:due_date].present? params[:due_date].present?
end end
......
module CalendarHelper
def calendar_url_options
{ format: :ics,
feed_token: current_user.try(:feed_token),
due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name,
sort: 'closest_future_date' }
end
end
module RssHelper module RssHelper
def rss_url_options def rss_url_options
{ format: :atom, rss_token: current_user.try(:rss_token) } { format: :atom, feed_token: current_user.try(:feed_token) }
end end
end end
...@@ -361,17 +361,6 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -361,17 +361,6 @@ class ApplicationSetting < ActiveRecord::Base
Array(read_attribute(:repository_storages)) Array(read_attribute(:repository_storages))
end end
# DEPRECATED
# repository_storage is still required in the API. Remove in 9.0
# Still used in API v3
def repository_storage
repository_storages.first
end
def repository_storage=(value)
self.repository_storages = [value]
end
def default_project_visibility=(level) def default_project_visibility=(level)
super(Gitlab::VisibilityLevel.level_value(level)) super(Gitlab::VisibilityLevel.level_value(level))
end end
......
# Provides a way to work around Rails issue where dependent objects are all
# loaded into memory before destroyed: https://github.com/rails/rails/issues/22510.
#
# This concern allows an ActiveRecord module to destroy all its dependent
# associations in batches. The idea is borrowed from https://github.com/thisismydesign/batch_dependent_associations.
#
# The differences here with that gem:
#
# 1. We allow excluding certain associations.
# 2. We don't need to support delete_all since we can use the EachBatch concern.
module BatchDestroyDependentAssociations
extend ActiveSupport::Concern
DEPENDENT_ASSOCIATIONS_BATCH_SIZE = 1000
def dependent_associations_to_destroy
self.class.reflect_on_all_associations(:has_many).select { |assoc| assoc.options[:dependent] == :destroy }
end
def destroy_dependent_associations_in_batches(exclude: [])
dependent_associations_to_destroy.each do |association|
next if exclude.include?(association.name)
# rubocop:disable GitlabSecurity/PublicSend
public_send(association.name).find_each(batch_size: DEPENDENT_ASSOCIATIONS_BATCH_SIZE, &:destroy)
end
end
end
# Makes api V3 compatible with old project features permissions methods # Makes api V4 compatible with old project features permissions methods
# #
# After migrating issues_enabled merge_requests_enabled builds_enabled snippets_enabled and wiki_enabled # After migrating issues_enabled merge_requests_enabled builds_enabled snippets_enabled and wiki_enabled
# fields to a new table "project_features", support for the old fields is still needed in the API. # fields to a new table "project_features", support for the old fields is still needed in the API.
......
...@@ -40,6 +40,7 @@ class Event < ActiveRecord::Base ...@@ -40,6 +40,7 @@ class Event < ActiveRecord::Base
).freeze ).freeze
RESET_PROJECT_ACTIVITY_INTERVAL = 1.hour RESET_PROJECT_ACTIVITY_INTERVAL = 1.hour
REPOSITORY_UPDATED_AT_INTERVAL = 5.minutes
delegate :name, :email, :public_email, :username, to: :author, prefix: true, allow_nil: true delegate :name, :email, :public_email, :username, to: :author, prefix: true, allow_nil: true
delegate :title, to: :issue, prefix: true, allow_nil: true delegate :title, to: :issue, prefix: true, allow_nil: true
...@@ -397,6 +398,7 @@ class Event < ActiveRecord::Base ...@@ -397,6 +398,7 @@ class Event < ActiveRecord::Base
def set_last_repository_updated_at def set_last_repository_updated_at
Project.unscoped.where(id: project_id) Project.unscoped.where(id: project_id)
.where("last_repository_updated_at < ? OR last_repository_updated_at IS NULL", REPOSITORY_UPDATED_AT_INTERVAL.ago)
.update_all(last_repository_updated_at: created_at) .update_all(last_repository_updated_at: created_at)
end end
......
...@@ -24,6 +24,7 @@ class Issue < ActiveRecord::Base ...@@ -24,6 +24,7 @@ class Issue < ActiveRecord::Base
Overdue = DueDateStruct.new('Overdue', 'overdue').freeze Overdue = DueDateStruct.new('Overdue', 'overdue').freeze
DueThisWeek = DueDateStruct.new('Due This Week', 'week').freeze DueThisWeek = DueDateStruct.new('Due This Week', 'week').freeze
DueThisMonth = DueDateStruct.new('Due This Month', 'month').freeze DueThisMonth = DueDateStruct.new('Due This Month', 'month').freeze
DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze
belongs_to :project belongs_to :project
belongs_to :moved_to, class_name: 'Issue' belongs_to :moved_to, class_name: 'Issue'
...@@ -53,6 +54,7 @@ class Issue < ActiveRecord::Base ...@@ -53,6 +54,7 @@ class Issue < ActiveRecord::Base
scope :unassigned, -> { where('NOT EXISTS (SELECT TRUE FROM issue_assignees WHERE issue_id = issues.id)') } scope :unassigned, -> { where('NOT EXISTS (SELECT TRUE FROM issue_assignees WHERE issue_id = issues.id)') }
scope :assigned_to, ->(u) { where('EXISTS (SELECT TRUE FROM issue_assignees WHERE user_id = ? AND issue_id = issues.id)', u.id)} scope :assigned_to, ->(u) { where('EXISTS (SELECT TRUE FROM issue_assignees WHERE user_id = ? AND issue_id = issues.id)', u.id)}
scope :with_due_date, -> { where('due_date IS NOT NULL') }
scope :without_due_date, -> { where(due_date: nil) } scope :without_due_date, -> { where(due_date: nil) }
scope :due_before, ->(date) { where('issues.due_date < ?', date) } scope :due_before, ->(date) { where('issues.due_date < ?', date) }
scope :due_between, ->(from_date, to_date) { where('issues.due_date >= ?', from_date).where('issues.due_date <= ?', to_date) } scope :due_between, ->(from_date, to_date) { where('issues.due_date >= ?', from_date).where('issues.due_date <= ?', to_date) }
...@@ -60,6 +62,7 @@ class Issue < ActiveRecord::Base ...@@ -60,6 +62,7 @@ class Issue < ActiveRecord::Base
scope :order_due_date_asc, -> { reorder('issues.due_date IS NULL, issues.due_date ASC') } scope :order_due_date_asc, -> { reorder('issues.due_date IS NULL, issues.due_date ASC') }
scope :order_due_date_desc, -> { reorder('issues.due_date IS NULL, issues.due_date DESC') } scope :order_due_date_desc, -> { reorder('issues.due_date IS NULL, issues.due_date DESC') }
scope :order_closest_future_date, -> { reorder('CASE WHEN due_date >= CURRENT_DATE THEN 0 ELSE 1 END ASC, ABS(CURRENT_DATE - due_date) ASC') }
scope :preload_associations, -> { preload(:labels, project: :namespace) } scope :preload_associations, -> { preload(:labels, project: :namespace) }
...@@ -126,6 +129,7 @@ class Issue < ActiveRecord::Base ...@@ -126,6 +129,7 @@ class Issue < ActiveRecord::Base
def self.sort_by_attribute(method, excluded_labels: []) def self.sort_by_attribute(method, excluded_labels: [])
case method.to_s case method.to_s
when 'closest_future_date' then order_closest_future_date
when 'due_date' then order_due_date_asc when 'due_date' then order_due_date_asc
when 'due_date_asc' then order_due_date_asc when 'due_date_asc' then order_due_date_asc
when 'due_date_desc' then order_due_date_desc when 'due_date_desc' then order_due_date_desc
......
...@@ -24,6 +24,7 @@ class Project < ActiveRecord::Base ...@@ -24,6 +24,7 @@ class Project < ActiveRecord::Base
include ChronicDurationAttribute include ChronicDurationAttribute
include FastDestroyAll::Helpers include FastDestroyAll::Helpers
include WithUploads include WithUploads
include BatchDestroyDependentAssociations
# EE specific modules # EE specific modules
prepend EE::Project prepend EE::Project
......
...@@ -207,10 +207,11 @@ class Service < ActiveRecord::Base ...@@ -207,10 +207,11 @@ class Service < ActiveRecord::Base
args.each do |arg| args.each do |arg|
class_eval %{ class_eval %{
def #{arg}? def #{arg}?
# '!!' is used because nil or empty string is converted to nil
if Gitlab.rails5? if Gitlab.rails5?
!ActiveModel::Type::Boolean::FALSE_VALUES.include?(#{arg}) !!ActiveRecord::Type::Boolean.new.cast(#{arg})
else else
ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(#{arg}) !!ActiveRecord::Type::Boolean.new.type_cast_from_database(#{arg})
end end
end end
} }
......
...@@ -28,7 +28,7 @@ class User < ActiveRecord::Base ...@@ -28,7 +28,7 @@ class User < ActiveRecord::Base
ignore_column :authentication_token ignore_column :authentication_token
add_authentication_token_field :incoming_email_token add_authentication_token_field :incoming_email_token
add_authentication_token_field :rss_token add_authentication_token_field :feed_token
default_value_for :admin, false default_value_for :admin, false
default_value_for(:external) { Gitlab::CurrentSettings.user_default_external } default_value_for(:external) { Gitlab::CurrentSettings.user_default_external }
...@@ -1189,11 +1189,11 @@ class User < ActiveRecord::Base ...@@ -1189,11 +1189,11 @@ class User < ActiveRecord::Base
save save
end end
# each existing user needs to have an `rss_token`. # each existing user needs to have an `feed_token`.
# we do this on read since migrating all existing users is not a feasible # we do this on read since migrating all existing users is not a feasible
# solution. # solution.
def rss_token def feed_token
ensure_rss_token! ensure_feed_token!
end end
def sync_attribute?(attribute) def sync_attribute?(attribute)
......
...@@ -31,7 +31,7 @@ class GroupChildEntity < Grape::Entity ...@@ -31,7 +31,7 @@ class GroupChildEntity < Grape::Entity
end end
# Project only attributes # Project only attributes
expose :star_count, expose :star_count, :archived,
if: lambda { |_instance, _options| project? } if: lambda { |_instance, _options| project? }
# Group only attributes # Group only attributes
......
...@@ -138,7 +138,13 @@ module Projects ...@@ -138,7 +138,13 @@ module Projects
trash_repositories! trash_repositories!
project.team.truncate # 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.
#
# Exclude container repositories because its before_destroy would be
# called multiple times, and it doesn't destroy any database records.
project.destroy_dependent_associations_in_batches(exclude: [:container_repositories])
project.destroy! project.destroy!
end end
end end
......
...@@ -11,6 +11,7 @@ module ObjectStorage ...@@ -11,6 +11,7 @@ module ObjectStorage
ObjectStorageUnavailable = Class.new(StandardError) ObjectStorageUnavailable = Class.new(StandardError)
DIRECT_UPLOAD_TIMEOUT = 4.hours DIRECT_UPLOAD_TIMEOUT = 4.hours
DIRECT_UPLOAD_EXPIRE_OFFSET = 15.minutes
TMP_UPLOAD_PATH = 'tmp/uploads'.freeze TMP_UPLOAD_PATH = 'tmp/uploads'.freeze
module Store module Store
...@@ -174,11 +175,12 @@ module ObjectStorage ...@@ -174,11 +175,12 @@ module ObjectStorage
id = [CarrierWave.generate_cache_id, SecureRandom.hex].join('-') id = [CarrierWave.generate_cache_id, SecureRandom.hex].join('-')
upload_path = File.join(TMP_UPLOAD_PATH, id) upload_path = File.join(TMP_UPLOAD_PATH, id)
connection = ::Fog::Storage.new(self.object_store_credentials) connection = ::Fog::Storage.new(self.object_store_credentials)
expire_at = Time.now + DIRECT_UPLOAD_TIMEOUT expire_at = Time.now + DIRECT_UPLOAD_TIMEOUT + DIRECT_UPLOAD_EXPIRE_OFFSET
options = { 'Content-Type' => 'application/octet-stream' } options = { 'Content-Type' => 'application/octet-stream' }
{ {
ID: id, ID: id,
Timeout: DIRECT_UPLOAD_TIMEOUT,
GetURL: connection.get_object_url(remote_store_path, upload_path, expire_at), GetURL: connection.get_object_url(remote_store_path, upload_path, expire_at),
DeleteURL: connection.delete_object_url(remote_store_path, upload_path, expire_at), DeleteURL: connection.delete_object_url(remote_store_path, upload_path, expire_at),
StoreURL: connection.put_object_url(remote_store_path, upload_path, expire_at, options) StoreURL: connection.put_object_url(remote_store_path, upload_path, expire_at, options)
......
...@@ -7,8 +7,7 @@ ...@@ -7,8 +7,7 @@
.top-area .top-area
= render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set = render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set
.nav-controls .nav-controls
= link_to safe_params.merge(rss_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: 'Subscribe' do = render 'shared/issuable/feed_buttons'
= icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
= render 'shared/issuable/filter', type: :issues = render 'shared/issuable/filter', type: :issues
......
= render 'issues/issues_calendar', issues: @issues
...@@ -8,10 +8,7 @@ ...@@ -8,10 +8,7 @@
.top-area .top-area
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls .nav-controls
= link_to safe_params.merge(rss_url_options), class: 'btn' do = render 'shared/issuable/feed_buttons'
= icon('rss')
%span.icon-label
Subscribe
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues
= render 'shared/issuable/search_bar', type: :issues = render 'shared/issuable/search_bar', type: :issues
......
= render 'issues/issues_calendar', issues: @issues
...@@ -8,13 +8,13 @@ ...@@ -8,13 +8,13 @@
= link_to edit_group_runner_path(@group, runner) do = link_to edit_group_runner_path(@group, runner) do
= icon('edit') = icon('edit')
.pull-right .float-right
- if runner.active? - if runner.active?
= link_to _('Pause'), pause_group_runner_path(@group, runner), method: :post, class: 'btn btn-sm btn-danger', data: { confirm: _("Are you sure?") } = link_to _('Pause'), pause_group_runner_path(@group, runner), method: :post, class: 'btn btn-sm btn-danger', data: { confirm: _("Are you sure?") }
- else - else
= link_to _('Resume'), resume_group_runner_path(@group, runner), method: :post, class: 'btn btn-success btn-sm' = link_to _('Resume'), resume_group_runner_path(@group, runner), method: :post, class: 'btn btn-success btn-sm'
= link_to _('Remove Runner'), group_runner_path(@group, runner), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn btn-danger btn-sm' = link_to _('Remove Runner'), group_runner_path(@group, runner), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn btn-danger btn-sm'
.pull-right .float-right
%small.light %small.light
\##{runner.id} \##{runner.id}
- if runner.description.present? - if runner.description.present?
......
cal = Icalendar::Calendar.new
cal.prodid = '-//GitLab//NONSGML GitLab//EN'
cal.x_wr_calname = 'GitLab Issues'
@issues.includes(project: :namespace).each do |issue|
cal.event do |event|
event.dtstart = Icalendar::Values::Date.new(issue.due_date)
event.summary = "#{issue.title} (in #{issue.project.full_path})"
event.description = "Find out more at #{issue_url(issue)}"
event.url = issue_url(issue)
event.transp = 'TRANSPARENT'
end
end
cal.to_ical
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
#js-peek{ data: { env: Peek.env, #js-peek{ data: { env: Peek.env,
request_id: Peek.request_id, request_id: Peek.request_id,
peek_url: peek_routes.results_url, peek_url: "#{peek_routes_path}/results",
profile_url: url_for(safe_params.merge(lineprofiler: 'true')) }, profile_url: url_for(safe_params.merge(lineprofiler: 'true')) },
class: Peek.env } class: Peek.env }
- is_current_session = active_session.current?(session) - is_current_session = active_session.current?(session)
%li.list-group-item %li.list-group-item
.pull-left.append-right-10{ data: { toggle: 'tooltip' }, title: active_session.human_device_type } .float-left.append-right-10{ data: { toggle: 'tooltip' }, title: active_session.human_device_type }
= active_session_device_type_icon(active_session) = active_session_device_type_icon(active_session)
.description.pull-left .description.float-left
%div %div
%strong= active_session.ip_address %strong= active_session.ip_address
- if is_current_session - if is_current_session
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
= l(active_session.created_at, format: :short) = l(active_session.created_at, format: :short)
- unless is_current_session - unless is_current_session
.pull-right .float-right
= link_to profile_active_session_path(active_session.session_id), data: { confirm: 'Are you sure? The device will be signed out of GitLab.' }, method: :delete, class: "btn btn-danger prepend-left-10" do = link_to profile_active_session_path(active_session.session_id), data: { confirm: 'Are you sure? The device will be signed out of GitLab.' }, method: :delete, class: "btn btn-danger prepend-left-10" do
%span.sr-only Revoke %span.sr-only Revoke
Revoke Revoke
...@@ -34,18 +34,18 @@ ...@@ -34,18 +34,18 @@
.row.prepend-top-default .row.prepend-top-default
.col-lg-4.profile-settings-sidebar .col-lg-4.profile-settings-sidebar
%h4.prepend-top-0 %h4.prepend-top-0
RSS token Feed token
%p %p
Your RSS token is used to authenticate you when your RSS reader loads a personalized RSS feed, and is included in your personal RSS feed URLs. Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when when your calendar application loads a personalized calendar, and is included in those feed URLs.
%p %p
It cannot be used to access any other data. It cannot be used to access any other data.
.col-lg-8.rss-token-reset .col-lg-8.feed-token-reset
= label_tag :rss_token, 'RSS token', class: "label-light" = label_tag :feed_token, 'Feed token', class: "label-light"
= text_field_tag :rss_token, current_user.rss_token, class: 'form-control', readonly: true, onclick: 'this.select()' = text_field_tag :feed_token, current_user.feed_token, class: 'form-control', readonly: true, onclick: 'this.select()'
%p.form-text.text-muted %p.form-text.text-muted
Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds as if they were you. Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you.
You should You should
= link_to 'reset it', [:reset, :rss_token, :profile], method: :put, data: { confirm: 'Are you sure? Any RSS URLs currently in use will stop working.' } = link_to 'reset it', [:reset, :feed_token, :profile], method: :put, data: { confirm: 'Are you sure? Any RSS or calendar URLs currently in use will stop working.' }
if that ever happens. if that ever happens.
- if incoming_email_token_enabled? - if incoming_email_token_enabled?
......
- form = local_assigns.fetch(:form)
- project = local_assigns.fetch(:project)
.form-check
= label_tag :project_merge_method_ff do
= form.radio_button :merge_method, :ff, class: "js-merge-method-radio qa-radio-button-merge-ff"
%strong Fast-forward merge
%br
%span.descr
No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.
%br
%span.descr
When fast-forward merge is not possible, the user is given the option to rebase.
- form = local_assigns.fetch(:form)
- project = local_assigns.fetch(:project)
.form-group
= label_tag :merge_method_merge, class: 'label-light' do
Merge method
.form-check
= label_tag :project_merge_method_merge do
= form.radio_button :merge_method, :merge, class: "js-merge-method-radio"
%strong Merge commit
%br
%span.descr
A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.
.form-check
= label_tag :project_merge_method_rebase_merge do
= form.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio"
%strong Merge commit with semi-linear history
%br
%span.descr
A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible.
This way you could make sure that if this merge request would build, after merging to target branch it would also build.
%br
%span.descr
When fast-forward merge is not possible, the user is given the option to rebase.
.form-check
= label_tag :project_merge_method_ff do
= form.radio_button :merge_method, :ff, class: "js-merge-method-radio qa-radio-button-merge-ff"
%strong Fast-forward merge
%br
%span.descr
No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.
%br
%span.descr
When fast-forward merge is not possible, the user is given the option to rebase.
- form = local_assigns.fetch(:form)
.form-check
= label_tag :project_merge_method_rebase_merge do
= form.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio"
%strong Merge commit with semi-linear history
%br
%span.descr
A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible.
This way you could make sure that if this merge request would build, after merging to target branch it would also build.
%br
%span.descr
When fast-forward merge is not possible, the user is given the option to rebase.
- form = local_assigns.fetch(:form) - form = local_assigns.fetch(:form)
.form-group = render 'projects/merge_request_merge_method_settings', project: @project, form: form
= label_tag :merge_method_merge, class: 'label-light' do
Merge method
.form-check
= label_tag :project_merge_method_merge do
= form.radio_button :merge_method, :merge, class: "js-merge-method-radio"
%strong Merge commit
%br
%span.descr
A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.
= render 'merge_request_rebase_settings', form: form
= render 'merge_request_fast_forward_settings', project: @project, form: form
= render 'projects/merge_request_merge_settings', form: form = render 'projects/merge_request_merge_settings', form: form
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
= s_('Branches|Cant find HEAD commit for this branch') = s_('Branches|Cant find HEAD commit for this branch')
- if branch.name != @repository.root_ref - if branch.name != @repository.root_ref
.divergence-graph.d-none.d-sm-block{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind), .divergence-graph.d-none.d-md-block{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind),
default_branch: @repository.root_ref, default_branch: @repository.root_ref,
number_commits_ahead: diverging_count_label(number_commits_ahead) } } number_commits_ahead: diverging_count_label(number_commits_ahead) } }
.graph-side .graph-side
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
.bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" } .bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" }
%span.count.count-ahead= diverging_count_label(number_commits_ahead) %span.count.count-ahead= diverging_count_label(number_commits_ahead)
.controls.d-none.d-sm-block< .controls.d-none.d-md-block<
- if merge_project && create_mr_button?(@repository.root_ref, branch.name) - if merge_project && create_mr_button?(@repository.root_ref, branch.name)
= link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do
= _('Merge request') = _('Merge request')
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
%span.dropdown-toggle-text %span.dropdown-toggle-text
= _('Select project') = _('Select project')
= icon('chevron-down') = icon('chevron-down')
%span.help-block &nbsp; %span.form-text.text-muted &nbsp;
.form-group .form-group
= provider_gcp_field.label :zone, s_('ClusterIntegration|Zone') = provider_gcp_field.label :zone, s_('ClusterIntegration|Zone')
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
.row .row
.col-sm-8.offset-sm-4.signin-with-google .col-sm-8.offset-sm-4.signin-with-google
- if @authorize_url - if @authorize_url
= link_to @authorize_url do = link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px'), @authorize_url)
= image_tag('auth_buttons/signin_with_google.png', width: '191px')
= _('or') = _('or')
= link_to('create a new Google account', 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral', target: '_blank', rel: 'noopener noreferrer') = link_to('create a new Google account', 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral', target: '_blank', rel: 'noopener noreferrer')
- else - else
......
...@@ -33,14 +33,14 @@ ...@@ -33,14 +33,14 @@
%span.light (optional) %span.light (optional)
= f.text_area :description, class: "form-control", rows: 3, maxlength: 250 = f.text_area :description, class: "form-control", rows: 3, maxlength: 250
= render 'projects/ee/classification_policy_settings', f: f = render_if_exists 'projects/classification_policy_settings', f: f
- unless @project.empty_repo? - unless @project.empty_repo?
.form-group .form-group
= f.label :default_branch, "Default Branch", class: 'label-light' = f.label :default_branch, "Default Branch", class: 'label-light'
= f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'}) = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'})
= render 'shared/repository_size_limit_setting', form: f, type: :project = render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
.form-group .form-group
= f.label :tag_list, "Tags", class: 'label-light' = f.label :tag_list, "Tags", class: 'label-light'
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
.js-project-permissions-form .js-project-permissions-form
= f.submit 'Save changes', class: "btn btn-save" = f.submit 'Save changes', class: "btn btn-save"
= render 'projects/ee/issues_settings' = render_if_exists 'projects/issues_settings'
%section.settings.merge-requests-feature.no-animate{ class: [('expanded' if expanded), ('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)] } %section.settings.merge-requests-feature.no-animate{ class: [('expanded' if expanded), ('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)] }
.settings-header .settings-header
...@@ -91,13 +91,13 @@ ...@@ -91,13 +91,13 @@
%p %p
Customize your merge request restrictions. Customize your merge request restrictions.
.settings-content .settings-content
= render 'shared/promotions/promote_mr_features' = render_if_exists 'shared/promotions/promote_mr_features'
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form" }, authenticity_token: true do |f| = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form" }, authenticity_token: true do |f|
= render 'projects/ee/merge_request_settings', form: f = render 'projects/merge_request_settings', form: f
= f.submit 'Save changes', class: "btn btn-save qa-save-merge-request-changes" = f.submit 'Save changes', class: "btn btn-save qa-save-merge-request-changes"
= render 'projects/ee/service_desk_settings' = render_if_exists 'projects/service_desk_settings'
= render 'export', project: @project = render 'export', project: @project
......
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
- show_export_button = local_assigns.fetch(:show_export_button, true) - show_export_button = local_assigns.fetch(:show_export_button, true)
- if show_rss_button - if show_rss_button
= link_to safe_params.merge(rss_url_options), class: 'btn btn-default append-right-10 has-tooltip', title: 'Subscribe' do = link_to safe_params.merge(rss_url_options), class: 'btn btn-default append-right-10 has-tooltip', title: 'Subscribe to RSS feed' do
= icon('rss') = icon('rss')
= link_to safe_params.merge(calendar_url_options), class: 'btn btn-default append-right-10 has-tooltip', title: 'Subscribe to calendar' do
= custom_icon('icon_calendar')
- if show_export_button - if show_export_button
= render 'projects/issues/export_issues/button' = render 'projects/issues/export_issues/button'
......
= render 'issues/issues_calendar', issues: @issues
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
= f.hidden_field(:team_id, value: selected_id, required: true) if @teams.one? = f.hidden_field(:team_id, value: selected_id, required: true) if @teams.one?
.form-text.text-muted .form-text.text-muted
- if @teams.one? - if @teams.one?
This is the only available team. This is the only available team that you are a member of.
- else - else
The list shows all available teams. The list shows all available teams that you are a member of.
To create a team, To create a team,
= link_to "#{Gitlab.config.mattermost.host}/create_team" do = link_to "#{Gitlab.config.mattermost.host}/create_team" do
use Mattermost's interface use Mattermost's interface
......
.row.empty-state .row.empty-state
.col-xs-12 .col-12
.svg-content .svg-content
= image_tag image_path = image_tag image_path
.col-xs-12 .col-12
.text-content.text-center .text-content.text-center
= yield = yield
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M15 5v7a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V5a2 2 0 0 1 2-2h1V2a1 1 0 1 1 2 0v1h4V2a1 1 0 1 1 2 0v1h1a2 2 0 0 1 2 2zM3 6v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V6H3zm2 2h2a1 1 0 1 1 0 2H5a1 1 0 1 1 0-2z" fill="#000" fill-rule="evenodd"/></svg>
\ No newline at end of file
= link_to safe_params.merge(rss_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: 'Subscribe to RSS feed' do
= icon('rss')
= link_to safe_params.merge(calendar_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: 'Subscribe to calendar' do
= custom_icon('icon_calendar')
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
= link_to user_snippets_path(snippet.author) do = link_to user_snippets_path(snippet.author) do
= snippet.author_name = snippet.author_name
- if link_project && snippet.project_id? - if link_project && snippet.project_id?
%span.d-none.d-sm-block %span.d-none.d-sm-inline-block
in in
= link_to project_path(snippet.project) do = link_to project_path(snippet.project) do
= snippet.project.full_name = snippet.project.full_name
......
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
= markdown_field(@term, :terms) = markdown_field(@term, :terms)
.row-content-block.footer-block.clearfix .row-content-block.footer-block.clearfix
- if can?(current_user, :accept_terms, @term) - if can?(current_user, :accept_terms, @term)
.pull-right .float-right
= button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8' do = button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8' do
= _('Accept terms') = _('Accept terms')
- if can?(current_user, :decline_terms, @term) - if can?(current_user, :decline_terms, @term)
.pull-right .float-right
= button_to decline_term_path(@term, redirect_params), class: 'btn btn-default prepend-left-8' do = button_to decline_term_path(@term, redirect_params), class: 'btn btn-default prepend-left-8' do
= _('Decline and sign out') = _('Decline and sign out')
---
title: Export assigned issues in iCalendar feed
merge_request: 17783
author: Imre Farkas
type: added
---
title: Change the IDE file buttons for an "Open in file view" button
merge_request: 19129
author: Sam Beckham
type: changed
---
title: Replace Gitlab::REVISION with Gitlab.revision and handle installations without
a .git directory
merge_request: 19125
author:
type: fixed
---
title: Update awesome_print to 1.8.0
merge_request: 19163
author: Takuya Noguchi
type: other
---
title: Update rdoc to 6.0.4
merge_request: 19167
author: Takuya Noguchi
type: other
---
title: Adjust permitted params filtering on merge scheduling
merge_request:
author:
type: fixed
---
title: Fix UI broken in line profiling modal due to Bootstrap 4
merge_request: 19253
author: Takuya Noguchi
type: other
---
title: Throttle updates to Project#last_repository_updated_at.
merge_request: 19183
author:
type: performance
---
title: Updates the version of kubeclient from 3.0 to 3.1.0
merge_request: 19199
author:
type: other
--- ---
title: Memoize Gitlab::Database.version title: Only preload member records for the relevant projects/groups/user in projects
API
merge_request: merge_request:
author: author:
type: performance type: performance
---
title: Fix remote mirror database inconsistencies when upgrading from EE to CE
merge_request: 19196
author:
type: fixed
---
title: Import bitbucket issues that are reported by an anonymous user
merge_request: 18199
author: bartl
type: fixed
---
title: Missing timeout value in object storage pre-authorization
merge_request: 19201
author:
type: fixed
---
title: Fix &nbsp; after sign-in with Google button
merge_request:
author:
type: fixed
---
title: Removed API v3 from the codebase
merge_request: 18970
author:
type: removed
---
title: Updated Mattermost integration to use API v4 and only allow creation of Mattermost slash commands in the current user's teams
merge_request: 19043
author: Harrison Healey
type: changed
---
title: Fix API to remove deploy key from project instead of deleting it entirely
merge_request:
author:
type: security
---
title: Fixed bug that allowed importing arbitrary project attributes
merge_request:
author:
type: security
---
title: Prevent user passwords from being changed without providing the previous password
merge_request:
author:
type: security
---
title: Fix project destruction failing due to idle in transaction timeouts
merge_request:
author:
type: fixed
---
title: Fix encoding of branch names on compare and new merge request page
merge_request: 19143
author:
type: fixed
...@@ -3,8 +3,8 @@ if defined?(Rails::Console) ...@@ -3,8 +3,8 @@ if defined?(Rails::Console)
# note that this will not print out when using `spring` # note that this will not print out when using `spring`
justify = 15 justify = 15
puts "-------------------------------------------------------------------------------------" puts "-------------------------------------------------------------------------------------"
puts " Gitlab:".ljust(justify) + "#{Gitlab::VERSION} (#{Gitlab.revision})" puts " GitLab:".ljust(justify) + "#{Gitlab::VERSION} (#{Gitlab.revision})"
puts " Gitlab Shell:".ljust(justify) + Gitlab::Shell.new.version puts " GitLab Shell:".ljust(justify) + "#{Gitlab::VersionInfo.parse(Gitlab::Shell.new.version)}"
puts " #{Gitlab::Database.adapter_name}:".ljust(justify) + Gitlab::Database.version puts " #{Gitlab::Database.adapter_name}:".ljust(justify) + Gitlab::Database.version
# EE-specific start # EE-specific start
......
resource :dashboard, controller: 'dashboard', only: [] do resource :dashboard, controller: 'dashboard', only: [] do
get :issues, action: :issues_calendar, constraints: lambda { |req| req.format == :ics }
get :issues get :issues
get :merge_requests get :merge_requests
get :activity get :activity
......
...@@ -5,9 +5,10 @@ end ...@@ -5,9 +5,10 @@ end
constraints(::Constraints::GroupUrlConstrainer.new) do constraints(::Constraints::GroupUrlConstrainer.new) do
scope(path: 'groups/*id', scope(path: 'groups/*id',
controller: :groups, controller: :groups,
constraints: { id: Gitlab::PathRegex.full_namespace_route_regex, format: /(html|json|atom)/ }) do constraints: { id: Gitlab::PathRegex.full_namespace_route_regex, format: /(html|json|atom|ics)/ }) do
scope(path: '-') do scope(path: '-') do
get :edit, as: :edit_group get :edit, as: :edit_group
get :issues, as: :issues_group_calendar, action: :issues_calendar, constraints: lambda { |req| req.format == :ics }
get :issues, as: :issues_group get :issues, as: :issues_group
get :merge_requests, as: :merge_requests_group get :merge_requests, as: :merge_requests_group
get :projects, as: :projects_group get :projects, as: :projects_group
...@@ -31,6 +32,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do ...@@ -31,6 +32,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
resource :variables, only: [:show, :update] resource :variables, only: [:show, :update]
resources :children, only: [:index] resources :children, only: [:index]
resources :shared_projects, only: [:index]
resources :labels, except: [:show] do resources :labels, except: [:show] do
post :toggle_subscription, on: :member post :toggle_subscription, on: :member
......
...@@ -7,7 +7,7 @@ resource :profile, only: [:show, :update] do ...@@ -7,7 +7,7 @@ resource :profile, only: [:show, :update] do
get :applications, to: 'oauth/applications#index' get :applications, to: 'oauth/applications#index'
put :reset_incoming_email_token put :reset_incoming_email_token
put :reset_rss_token put :reset_feed_token
put :update_username put :update_username
end end
......
...@@ -389,6 +389,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -389,6 +389,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
## EE-specific ## EE-specific
resources :vulnerability_feedback, only: [:index, :create, :destroy], constraints: { id: /\d+/ } resources :vulnerability_feedback, only: [:index, :create, :destroy], constraints: { id: /\d+/ }
get :issues, to: 'issues#calendar', constraints: lambda { |req| req.format == :ics }
resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do
member do member do
post :toggle_subscription post :toggle_subscription
......
class RenameUsersRssTokenToFeedToken < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
rename_column_concurrently :users, :rss_token, :feed_token
end
def down
cleanup_concurrent_column_rename :users, :feed_token, :rss_token
end
end
class CleanupUsersRssTokenRename < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
cleanup_concurrent_column_rename :users, :rss_token, :feed_token
end
def down
rename_column_concurrently :users, :feed_token, :rss_token
end
end
...@@ -2657,13 +2657,13 @@ ActiveRecord::Schema.define(version: 20180529093006) do ...@@ -2657,13 +2657,13 @@ ActiveRecord::Schema.define(version: 20180529093006) do
t.boolean "notified_of_own_activity" t.boolean "notified_of_own_activity"
t.boolean "support_bot" t.boolean "support_bot"
t.string "preferred_language" t.string "preferred_language"
t.string "rss_token"
t.boolean "email_opted_in" t.boolean "email_opted_in"
t.string "email_opted_in_ip" t.string "email_opted_in_ip"
t.integer "email_opted_in_source_id" t.integer "email_opted_in_source_id"
t.datetime "email_opted_in_at" t.datetime "email_opted_in_at"
t.integer "theme_id", limit: 2 t.integer "theme_id", limit: 2
t.integer "accepted_term_id" t.integer "accepted_term_id"
t.string "feed_token"
end end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
...@@ -2671,12 +2671,12 @@ ActiveRecord::Schema.define(version: 20180529093006) do ...@@ -2671,12 +2671,12 @@ ActiveRecord::Schema.define(version: 20180529093006) do
add_index "users", ["created_at"], name: "index_users_on_created_at", using: :btree add_index "users", ["created_at"], name: "index_users_on_created_at", using: :btree
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["email"], name: "index_users_on_email_trigram", using: :gin, opclasses: {"email"=>"gin_trgm_ops"} add_index "users", ["email"], name: "index_users_on_email_trigram", using: :gin, opclasses: {"email"=>"gin_trgm_ops"}
add_index "users", ["feed_token"], name: "index_users_on_feed_token", using: :btree
add_index "users", ["ghost"], name: "index_users_on_ghost", using: :btree add_index "users", ["ghost"], name: "index_users_on_ghost", using: :btree
add_index "users", ["incoming_email_token"], name: "index_users_on_incoming_email_token", using: :btree add_index "users", ["incoming_email_token"], name: "index_users_on_incoming_email_token", using: :btree
add_index "users", ["name"], name: "index_users_on_name", using: :btree add_index "users", ["name"], name: "index_users_on_name", using: :btree
add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"} add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_index "users", ["rss_token"], name: "index_users_on_rss_token", using: :btree
add_index "users", ["state"], name: "index_users_on_state", using: :btree add_index "users", ["state"], name: "index_users_on_state", using: :btree
add_index "users", ["support_bot"], name: "index_users_on_support_bot", using: :btree add_index "users", ["support_bot"], name: "index_users_on_support_bot", using: :btree
add_index "users", ["username"], name: "index_users_on_username", using: :btree add_index "users", ["username"], name: "index_users_on_username", using: :btree
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
> >
**Note:** Custom Git hooks must be configured on the filesystem of the GitLab **Note:** Custom Git hooks must be configured on the filesystem of the GitLab
server. Only GitLab server administrators will be able to complete these tasks. server. Only GitLab server administrators will be able to complete these tasks.
Please explore [webhooks] as an option if you do not Please explore [webhooks] and [CI] as an option if you do not
have filesystem access. For a user configurable Git hook interface, see have filesystem access. For a user configurable Git hook interface, see
[Push Rules](https://docs.gitlab.com/ee/push_rules/push_rules.html), [Push Rules](https://docs.gitlab.com/ee/push_rules/push_rules.html),
available in GitLab Enterprise Edition. available in GitLab Enterprise Edition.
...@@ -83,6 +83,7 @@ STDERR takes precedence over STDOUT. ...@@ -83,6 +83,7 @@ STDERR takes precedence over STDOUT.
![Custom message from custom Git hook](img/custom_hooks_error_msg.png) ![Custom message from custom Git hook](img/custom_hooks_error_msg.png)
[CI]: ../ci/README.md
[hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks [hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks
[webhooks]: ../user/project/integrations/webhooks.md [webhooks]: ../user/project/integrations/webhooks.md
[gitlab-geo]: ../administration/geo/replication/index.md [gitlab-geo]: ../administration/geo/replication/index.md
......
...@@ -47,7 +47,8 @@ for each GitLab application server in your environment. ...@@ -47,7 +47,8 @@ for each GitLab application server in your environment.
URL. Depending your the NFS configuration, you may need to change some GitLab URL. Depending your the NFS configuration, you may need to change some GitLab
data locations. See [NFS documentation](nfs.md) for `/etc/gitlab/gitlab.rb` data locations. See [NFS documentation](nfs.md) for `/etc/gitlab/gitlab.rb`
configuration values for various scenarios. The example below assumes you've configuration values for various scenarios. The example below assumes you've
added NFS mounts in the default data locations. added NFS mounts in the default data locations. Additionally the UID and GIDs
given are just examples and you should configure with your preferred values.
```ruby ```ruby
external_url 'https://gitlab.example.com' external_url 'https://gitlab.example.com'
...@@ -69,6 +70,14 @@ for each GitLab application server in your environment. ...@@ -69,6 +70,14 @@ for each GitLab application server in your environment.
gitlab_rails['redis_port'] = '6379' gitlab_rails['redis_port'] = '6379'
gitlab_rails['redis_host'] = '10.1.0.6' # IP/hostname of Redis server gitlab_rails['redis_host'] = '10.1.0.6' # IP/hostname of Redis server
gitlab_rails['redis_password'] = 'Redis Password' gitlab_rails['redis_password'] = 'Redis Password'
# Ensure UIDs and GIDs match between servers for permissions via NFS
user['uid'] = 9000
user['gid'] = 9000
web_server['uid'] = 9001
web_server['gid'] = 9001
registry['uid'] = 9002
registry['gid'] = 9002
``` ```
> **Note:** To maintain uniformity of links across HA clusters, the `external_url` > **Note:** To maintain uniformity of links across HA clusters, the `external_url`
......
...@@ -25,7 +25,9 @@ options: ...@@ -25,7 +25,9 @@ options:
errors when the Omnibus package tries to alter permissions. Note that GitLab errors when the Omnibus package tries to alter permissions. Note that GitLab
and other bundled components do **not** run as `root` but as non-privileged and other bundled components do **not** run as `root` but as non-privileged
users. The recommendation for `no_root_squash` is to allow the Omnibus package users. The recommendation for `no_root_squash` is to allow the Omnibus package
to set ownership and permissions on files, as needed. to set ownership and permissions on files, as needed. In some cases where the
`no_root_squash` option is not available, the `root` flag can achieve the same
result.
- `sync` - Force synchronous behavior. Default is asynchronous and under certain - `sync` - Force synchronous behavior. Default is asynchronous and under certain
circumstances it could lead to data loss if a failure occurs before data has circumstances it could lead to data loss if a failure occurs before data has
synced. synced.
......
...@@ -24,7 +24,6 @@ gitlab-rake gitlab:storage:migrate_to_hashed ...@@ -24,7 +24,6 @@ gitlab-rake gitlab:storage:migrate_to_hashed
```bash ```bash
rake gitlab:storage:migrate_to_hashed rake gitlab:storage:migrate_to_hashed
``` ```
You can monitor the progress in the _Admin > Monitoring > Background jobs_ screen. You can monitor the progress in the _Admin > Monitoring > Background jobs_ screen.
...@@ -52,7 +51,6 @@ gitlab-rake gitlab:storage:legacy_projects ...@@ -52,7 +51,6 @@ gitlab-rake gitlab:storage:legacy_projects
```bash ```bash
rake gitlab:storage:legacy_projects rake gitlab:storage:legacy_projects
``` ```
------ ------
...@@ -86,7 +84,6 @@ gitlab-rake gitlab:storage:hashed_projects ...@@ -86,7 +84,6 @@ gitlab-rake gitlab:storage:hashed_projects
```bash ```bash
rake gitlab:storage:hashed_projects rake gitlab:storage:hashed_projects
``` ```
------ ------
...@@ -120,7 +117,6 @@ gitlab-rake gitlab:storage:legacy_attachments ...@@ -120,7 +117,6 @@ gitlab-rake gitlab:storage:legacy_attachments
```bash ```bash
rake gitlab:storage:legacy_attachments rake gitlab:storage:legacy_attachments
``` ```
------ ------
...@@ -137,7 +133,6 @@ gitlab-rake gitlab:storage:list_legacy_attachments ...@@ -137,7 +133,6 @@ gitlab-rake gitlab:storage:list_legacy_attachments
```bash ```bash
rake gitlab:storage:list_legacy_attachments rake gitlab:storage:list_legacy_attachments
``` ```
## List attachments on Hashed storage ## List attachments on Hashed storage
...@@ -154,7 +149,6 @@ gitlab-rake gitlab:storage:hashed_attachments ...@@ -154,7 +149,6 @@ gitlab-rake gitlab:storage:hashed_attachments
```bash ```bash
rake gitlab:storage:hashed_attachments rake gitlab:storage:hashed_attachments
``` ```
------ ------
...@@ -171,7 +165,6 @@ gitlab-rake gitlab:storage:list_hashed_attachments ...@@ -171,7 +165,6 @@ gitlab-rake gitlab:storage:list_hashed_attachments
```bash ```bash
rake gitlab:storage:list_hashed_attachments rake gitlab:storage:list_hashed_attachments
``` ```
[storage-types]: ../repository_storage_types.md [storage-types]: ../repository_storage_types.md
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment