Commit 0cb6b787 authored by Arun Kumar Mohan's avatar Arun Kumar Mohan

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into db/update-geo-nodes-primary

parents a10d80ea 4298a28a
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.29" image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.29"
variables: variables:
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
RAILS_ENV: "test" RAILS_ENV: "test"
NODE_ENV: "test" NODE_ENV: "test"
SIMPLECOV: "true" SIMPLECOV: "true"
...@@ -37,6 +36,7 @@ include: ...@@ -37,6 +36,7 @@ include:
- local: .gitlab/ci/cng.gitlab-ci.yml - local: .gitlab/ci/cng.gitlab-ci.yml
- local: .gitlab/ci/docs.gitlab-ci.yml - local: .gitlab/ci/docs.gitlab-ci.yml
- local: .gitlab/ci/frontend.gitlab-ci.yml - local: .gitlab/ci/frontend.gitlab-ci.yml
- local: .gitlab/ci/memory.gitlab-ci.yml
- local: .gitlab/ci/pages.gitlab-ci.yml - local: .gitlab/ci/pages.gitlab-ci.yml
- local: .gitlab/ci/qa.gitlab-ci.yml - local: .gitlab/ci/qa.gitlab-ci.yml
- local: .gitlab/ci/reports.gitlab-ci.yml - local: .gitlab/ci/reports.gitlab-ci.yml
......
memory-static:
extends: .dedicated-no-docs-no-db-pull-cache-job
script:
# Uses two different reports from the 'derailed_benchmars' gem.
# Loads each of gems in the Gemfile and checks how much memory they consume when they are required.
# 'derailed_benchmarks' internally uses 'get_process_mem'
- scripts/memory-static 'tmp/memory_static_full_report.txt' 'tmp/memory_static_metrics.txt'
# Outputs detailed information about objects created while gems are loaded.
# 'derailed_benchmarks' internally uses 'memory_profiler'
- scripts/memory-static-objects 'tmp/memory_static_objects_full_report.txt' 'tmp/memory_static_metrics.txt'
artifacts:
paths:
- tmp/memory_static_full_report.txt
- tmp/memory_static_objects_full_report.txt
- tmp/memory_static_metrics.txt
reports:
metrics: tmp/memory_static_metrics.txt
...@@ -10,11 +10,6 @@ ...@@ -10,11 +10,6 @@
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine - name: redis:alpine
.use-mysql: &use-mysql
services:
- mysql:5.7
- redis:alpine
.only-schedules-master: &only-schedules-master .only-schedules-master: &only-schedules-master
only: only:
- schedules@gitlab-org/gitlab-ce - schedules@gitlab-org/gitlab-ce
...@@ -94,10 +89,6 @@ ...@@ -94,10 +89,6 @@
<<: *use-pg-10 <<: *use-pg-10
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-12.x-yarn-1.16-postgresql-10-graphicsmagick-1.3.29" image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-12.x-yarn-1.16-postgresql-10-graphicsmagick-1.3.29"
.rspec-metadata-mysql: &rspec-metadata-mysql
<<: *rspec-metadata
<<: *use-mysql
# DB migration, rollback, and seed jobs # DB migration, rollback, and seed jobs
.db-migrate-reset: &db-migrate-reset .db-migrate-reset: &db-migrate-reset
extends: .dedicated-no-docs-and-no-qa-pull-cache-job extends: .dedicated-no-docs-and-no-qa-pull-cache-job
...@@ -173,42 +164,6 @@ rspec system pg-10: ...@@ -173,42 +164,6 @@ rspec system pg-10:
<<: *only-schedules-master <<: *only-schedules-master
parallel: 24 parallel: 24
rspec unit mysql:
<<: *rspec-metadata-mysql
<<: *only-schedules-master
parallel: 20
rspec integration mysql:
<<: *rspec-metadata-mysql
<<: *only-schedules-master
parallel: 6
rspec system mysql:
<<: *rspec-metadata-mysql
<<: *only-schedules-master
parallel: 24
.rspec-mysql-on-demand: &rspec-mysql-on-demand
only:
variables:
- $CI_COMMIT_MESSAGE =~ /\[run mysql\]/i
- $CI_COMMIT_REF_NAME =~ /mysql/
rspec unit mysql on-demand:
<<: *rspec-metadata-mysql
<<: *rspec-mysql-on-demand
parallel: 20
rspec integration mysql on-demand:
<<: *rspec-metadata-mysql
<<: *rspec-mysql-on-demand
parallel: 6
rspec system mysql on-demand:
<<: *rspec-metadata-mysql
<<: *rspec-mysql-on-demand
parallel: 24
rspec-fast-spec-helper: rspec-fast-spec-helper:
<<: *rspec-metadata-pg <<: *rspec-metadata-pg
script: script:
...@@ -226,12 +181,6 @@ rspec quarantine pg: ...@@ -226,12 +181,6 @@ rspec quarantine pg:
<<: *rspec-quarantine <<: *rspec-quarantine
allow_failure: true allow_failure: true
rspec quarantine mysql:
<<: *rspec-metadata-mysql
<<: *rspec-quarantine
<<: *only-schedules-master
allow_failure: true
static-analysis: static-analysis:
extends: .dedicated-no-docs-no-db-pull-cache-job extends: .dedicated-no-docs-no-db-pull-cache-job
dependencies: dependencies:
...@@ -281,10 +230,6 @@ db:migrate:reset-pg: ...@@ -281,10 +230,6 @@ db:migrate:reset-pg:
<<: *db-migrate-reset <<: *db-migrate-reset
<<: *use-pg <<: *use-pg
db:migrate:reset-mysql:
<<: *db-migrate-reset
<<: *use-mysql
db:check-schema-pg: db:check-schema-pg:
<<: *db-migrate-reset <<: *db-migrate-reset
<<: *use-pg <<: *use-pg
...@@ -295,10 +240,6 @@ migration:path-pg: ...@@ -295,10 +240,6 @@ migration:path-pg:
<<: *migration-paths <<: *migration-paths
<<: *use-pg <<: *use-pg
migration:path-mysql:
<<: *migration-paths
<<: *use-mysql
.db-rollback: &db-rollback .db-rollback: &db-rollback
extends: .dedicated-no-docs-and-no-qa-pull-cache-job extends: .dedicated-no-docs-and-no-qa-pull-cache-job
script: script:
...@@ -311,22 +252,12 @@ db:rollback-pg: ...@@ -311,22 +252,12 @@ db:rollback-pg:
<<: *db-rollback <<: *db-rollback
<<: *use-pg <<: *use-pg
db:rollback-mysql:
<<: *db-rollback
<<: *use-mysql
gitlab:setup-pg: gitlab:setup-pg:
<<: *gitlab-setup <<: *gitlab-setup
<<: *use-pg <<: *use-pg
dependencies: dependencies:
- setup-test-env - setup-test-env
gitlab:setup-mysql:
<<: *gitlab-setup
<<: *use-mysql
dependencies:
- setup-test-env
coverage: coverage:
# Don't include dedicated-no-docs-no-db-pull-cache-job here since we need to # Don't include dedicated-no-docs-no-db-pull-cache-job here since we need to
# download artifacts from all the rspec jobs instead of from setup-test-env only # download artifacts from all the rspec jobs instead of from setup-test-env only
......
...@@ -12,6 +12,7 @@ const Api = { ...@@ -12,6 +12,7 @@ const Api = {
groupProjectsPath: '/api/:version/groups/:id/projects.json', groupProjectsPath: '/api/:version/groups/:id/projects.json',
projectsPath: '/api/:version/projects.json', projectsPath: '/api/:version/projects.json',
projectPath: '/api/:version/projects/:id', projectPath: '/api/:version/projects/:id',
forkedProjectsPath: '/api/:version/projects/:id/forks',
projectLabelsPath: '/:namespace_path/:project_path/-/labels', projectLabelsPath: '/:namespace_path/:project_path/-/labels',
projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests', projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid', projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
...@@ -113,6 +114,21 @@ const Api = { ...@@ -113,6 +114,21 @@ const Api = {
return axios.get(url); return axios.get(url);
}, },
/**
* Get all projects for a forked relationship to a specified project
* @param {string} projectPath - Path or ID of a project
* @param {Object} params - Get request parameters
* @returns {Promise} - Request promise
*/
projectForks(projectPath, params) {
const url = Api.buildUrl(Api.forkedProjectsPath).replace(
':id',
encodeURIComponent(projectPath),
);
return axios.get(url, { params });
},
/** /**
* Get all Merge Requests for a project, eventually filtering based on * Get all Merge Requests for a project, eventually filtering based on
* supplied parameters * supplied parameters
......
...@@ -4,7 +4,7 @@ import { GlTooltipDirective } from '@gitlab/ui'; ...@@ -4,7 +4,7 @@ import { GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import Suggestion from './item.vue'; import Suggestion from './item.vue';
import query from '../queries/issues.graphql'; import query from '../queries/issues.query.graphql';
export default { export default {
components: { components: {
......
...@@ -3,7 +3,7 @@ import { GlPopover, GlSkeletonLoading } from '@gitlab/ui'; ...@@ -3,7 +3,7 @@ import { GlPopover, GlSkeletonLoading } from '@gitlab/ui';
import Icon from '../../vue_shared/components/icon.vue'; import Icon from '../../vue_shared/components/icon.vue';
import CiIcon from '../../vue_shared/components/ci_icon.vue'; import CiIcon from '../../vue_shared/components/ci_icon.vue';
import timeagoMixin from '../../vue_shared/mixins/timeago'; import timeagoMixin from '../../vue_shared/mixins/timeago';
import query from '../queries/merge_request.graphql'; import query from '../queries/merge_request.query.graphql';
import { mrStates, humanMRStates } from '../constants'; import { mrStates, humanMRStates } from '../constants';
export default { export default {
......
...@@ -7,8 +7,8 @@ import OAuthRememberMe from './oauth_remember_me'; ...@@ -7,8 +7,8 @@ import OAuthRememberMe from './oauth_remember_me';
import preserveUrlFragment from './preserve_url_fragment'; import preserveUrlFragment from './preserve_url_fragment';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
new LengthValidator(); // eslint-disable-line no-new
new UsernameValidator(); // eslint-disable-line no-new new UsernameValidator(); // eslint-disable-line no-new
new LengthValidator(); // eslint-disable-line no-new
new SigninTabsMemoizer(); // eslint-disable-line no-new new SigninTabsMemoizer(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new new NoEmojiValidator(); // eslint-disable-line no-new
......
/* eslint-disable consistent-return, class-methods-use-this */ import InputValidator from '~/validators/input_validator';
import $ from 'jquery';
import _ from 'underscore'; import _ from 'underscore';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import flash from '~/flash'; import flash from '~/flash';
import { __ } from '~/locale'; import { __ } from '~/locale';
const debounceTimeoutDuration = 1000; const debounceTimeoutDuration = 1000;
const rootUrl = gon.relative_url_root;
const invalidInputClass = 'gl-field-error-outline'; const invalidInputClass = 'gl-field-error-outline';
const successInputClass = 'gl-field-success-outline'; const successInputClass = 'gl-field-success-outline';
const unavailableMessageSelector = '.username .validation-error'; const successMessageSelector = '.validation-success';
const successMessageSelector = '.username .validation-success'; const pendingMessageSelector = '.validation-pending';
const pendingMessageSelector = '.username .validation-pending'; const unavailableMessageSelector = '.validation-error';
const invalidMessageSelector = '.username .gl-field-error';
export default class UsernameValidator { export default class UsernameValidator extends InputValidator {
constructor() { constructor(opts = {}) {
this.inputElement = $('#new_user_username'); super();
this.inputDomElement = this.inputElement.get(0);
this.state = {
available: false,
valid: false,
pending: false,
empty: true,
};
const debounceTimeout = _.debounce(username => { const container = opts.container || '';
this.validateUsername(username); const validateLengthElements = document.querySelectorAll(`${container} .js-validate-username`);
}, debounceTimeoutDuration);
this.inputElement.on('keyup.username_check', () => {
const username = this.inputElement.val();
this.state.valid = this.inputDomElement.validity.valid;
this.state.empty = !username.length;
if (this.state.valid) {
return debounceTimeout(username);
}
this.renderState();
});
// Override generic field validation
this.inputElement.on('invalid', this.interceptInvalid.bind(this));
}
renderState() {
// Clear all state
this.clearFieldValidationState();
if (this.state.valid && this.state.available) {
return this.setSuccessState();
}
if (this.state.empty) { this.debounceValidateInput = _.debounce(inputDomElement => {
return this.clearFieldValidationState(); UsernameValidator.validateUsernameInput(inputDomElement);
} }, debounceTimeoutDuration);
if (this.state.pending) { validateLengthElements.forEach(element =>
return this.setPendingState(); element.addEventListener('input', this.eventHandler.bind(this)),
);
} }
if (!this.state.valid) { eventHandler(event) {
return this.setInvalidState(); const inputDomElement = event.target;
}
if (!this.state.available) { UsernameValidator.resetInputState(inputDomElement);
return this.setUnavailableState(); this.debounceValidateInput(inputDomElement);
}
} }
interceptInvalid(event) { static validateUsernameInput(inputDomElement) {
event.preventDefault(); const username = inputDomElement.value;
event.stopPropagation();
}
validateUsername(username) { if (inputDomElement.checkValidity() && username.length > 0) {
if (this.state.valid) { UsernameValidator.setMessageVisibility(inputDomElement, pendingMessageSelector);
this.state.pending = true; UsernameValidator.fetchUsernameAvailability(username)
this.state.available = false; .then(usernameTaken => {
this.renderState(); UsernameValidator.setInputState(inputDomElement, !usernameTaken);
axios UsernameValidator.setMessageVisibility(inputDomElement, pendingMessageSelector, false);
.get(`${gon.relative_url_root}/users/${username}/exists`) UsernameValidator.setMessageVisibility(
.then(({ data }) => this.setAvailabilityState(data.exists)) inputDomElement,
usernameTaken ? unavailableMessageSelector : successMessageSelector,
);
})
.catch(() => flash(__('An error occurred while validating username'))); .catch(() => flash(__('An error occurred while validating username')));
} }
} }
setAvailabilityState(usernameTaken) { static fetchUsernameAvailability(username) {
if (usernameTaken) { return axios.get(`${rootUrl}/users/${username}/exists`).then(({ data }) => data.exists);
this.state.available = false;
} else {
this.state.available = true;
} }
this.state.pending = false;
this.renderState();
}
clearFieldValidationState() {
this.inputElement.siblings('p').hide();
this.inputElement.removeClass(invalidInputClass).removeClass(successInputClass); static setMessageVisibility(inputDomElement, messageSelector, isVisible = true) {
const messageElement = inputDomElement.parentElement.querySelector(messageSelector);
messageElement.classList.toggle('hide', !isVisible);
} }
setUnavailableState() { static setInputState(inputDomElement, success = true) {
const $usernameUnavailableMessage = this.inputElement.siblings(unavailableMessageSelector); inputDomElement.classList.toggle(successInputClass, success);
this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); inputDomElement.classList.toggle(invalidInputClass, !success);
$usernameUnavailableMessage.show();
} }
setSuccessState() { static resetInputState(inputDomElement) {
const $usernameSuccessMessage = this.inputElement.siblings(successMessageSelector); UsernameValidator.setMessageVisibility(inputDomElement, successMessageSelector, false);
this.inputElement.addClass(successInputClass).removeClass(invalidInputClass); UsernameValidator.setMessageVisibility(inputDomElement, unavailableMessageSelector, false);
$usernameSuccessMessage.show();
}
setPendingState() { if (inputDomElement.checkValidity()) {
const $usernamePendingMessage = $(pendingMessageSelector); inputDomElement.classList.remove(successInputClass, invalidInputClass);
if (this.state.pending) {
$usernamePendingMessage.show();
} else {
$usernamePendingMessage.hide();
} }
} }
setInvalidState() {
const $inputErrorMessage = $(invalidMessageSelector);
this.inputElement.addClass(invalidInputClass).removeClass(successInputClass);
$inputErrorMessage.show();
}
} }
<script> <script>
import getRefMixin from '../mixins/get_ref'; import getRefMixin from '../mixins/get_ref';
import getProjectShortPath from '../queries/getProjectShortPath.graphql'; import getProjectShortPath from '../queries/getProjectShortPath.query.graphql';
export default { export default {
apollo: { apollo: {
......
...@@ -3,8 +3,8 @@ import { GlLoadingIcon } from '@gitlab/ui'; ...@@ -3,8 +3,8 @@ import { GlLoadingIcon } from '@gitlab/ui';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { sprintf, __ } from '../../../locale'; import { sprintf, __ } from '../../../locale';
import getRefMixin from '../../mixins/get_ref'; import getRefMixin from '../../mixins/get_ref';
import getFiles from '../../queries/getFiles.graphql'; import getFiles from '../../queries/getFiles.query.graphql';
import getProjectPath from '../../queries/getProjectPath.graphql'; import getProjectPath from '../../queries/getProjectPath.query.graphql';
import TableHeader from './header.vue'; import TableHeader from './header.vue';
import TableRow from './row.vue'; import TableRow from './row.vue';
import ParentRow from './parent_row.vue'; import ParentRow from './parent_row.vue';
......
import getRef from '../queries/getRef.graphql'; import getRef from '../queries/getRef.query.graphql';
export default { export default {
apollo: { apollo: {
......
...@@ -199,7 +199,6 @@ ...@@ -199,7 +199,6 @@
&.user-cover-block { &.user-cover-block {
padding: 24px 0 0; padding: 24px 0 0;
border-bottom: 1px solid $border-color;
.nav-links { .nav-links {
width: 100%; width: 100%;
......
...@@ -221,6 +221,11 @@ ...@@ -221,6 +221,11 @@
ol { ol {
padding: 0; padding: 0;
margin: 0 0 16px; margin: 0 0 16px;
ul,
ol {
margin-bottom: 0;
}
} }
ul:dir(rtl), ul:dir(rtl),
......
...@@ -31,8 +31,12 @@ class Projects::JobsController < Projects::ApplicationController ...@@ -31,8 +31,12 @@ class Projects::JobsController < Projects::ApplicationController
@builds @builds
end end
@builds = @builds.includes([ @builds = @builds.includes([
{ pipeline: :project }, { pipeline: [:project, :user] },
:job_artifacts_archive,
:metadata,
:trigger_request,
:project, :project,
:user,
:tags :tags
]) ])
@builds = @builds.page(params[:page]).per(30).without_count @builds = @builds.page(params[:page]).per(30).without_count
......
...@@ -8,8 +8,7 @@ class Projects::TagsController < Projects::ApplicationController ...@@ -8,8 +8,7 @@ class Projects::TagsController < Projects::ApplicationController
# Authorize # Authorize
before_action :require_non_empty_project before_action :require_non_empty_project
before_action :authorize_download_code! before_action :authorize_download_code!
before_action :authorize_push_code!, only: [:new, :create] before_action :authorize_admin_tag!, only: [:new, :create, :destroy]
before_action :authorize_admin_project!, only: [:destroy]
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def index def index
......
...@@ -34,8 +34,10 @@ class NotesFinder ...@@ -34,8 +34,10 @@ class NotesFinder
target_type = @params[:target_type] target_type = @params[:target_type]
target_id = @params[:target_id] target_id = @params[:target_id]
target_iid = @params[:target_iid]
return @target = nil unless target_type && target_id return @target = nil unless target_type
return @target = nil unless target_id || target_iid
@target = @target =
if target_type == "commit" if target_type == "commit"
...@@ -43,12 +45,22 @@ class NotesFinder ...@@ -43,12 +45,22 @@ class NotesFinder
@project.commit(target_id) @project.commit(target_id)
end end
else else
noteables_for_type(target_type).find(target_id) noteables_for_type_by_id(target_type, target_id, target_iid)
end end
end end
private private
def noteables_for_type_by_id(type, id, iid)
query = if id
{ id: id }
else
{ iid: iid }
end
noteables_for_type(type).find_by!(query) # rubocop: disable CodeReuse/ActiveRecord
end
def init_collection def init_collection
if target if target
notes_on_target notes_on_target
......
...@@ -4,6 +4,7 @@ module Types ...@@ -4,6 +4,7 @@ module Types
class BaseObject < GraphQL::Schema::Object class BaseObject < GraphQL::Schema::Object
prepend Gitlab::Graphql::Present prepend Gitlab::Graphql::Present
prepend Gitlab::Graphql::ExposePermissions prepend Gitlab::Graphql::ExposePermissions
prepend Gitlab::Graphql::MarkdownField
field_class Types::BaseField field_class Types::BaseField
......
...@@ -14,7 +14,9 @@ module Types ...@@ -14,7 +14,9 @@ module Types
field :iid, GraphQL::ID_TYPE, null: false field :iid, GraphQL::ID_TYPE, null: false
field :title, GraphQL::STRING_TYPE, null: false field :title, GraphQL::STRING_TYPE, null: false
markdown_field :title_html, null: true
field :description, GraphQL::STRING_TYPE, null: true field :description, GraphQL::STRING_TYPE, null: true
markdown_field :description_html, null: true
field :state, IssueStateEnum, null: false field :state, IssueStateEnum, null: false
field :reference, GraphQL::STRING_TYPE, null: false, method: :to_reference do field :reference, GraphQL::STRING_TYPE, null: false, method: :to_reference do
......
...@@ -5,6 +5,7 @@ module Types ...@@ -5,6 +5,7 @@ module Types
graphql_name 'Label' graphql_name 'Label'
field :description, GraphQL::STRING_TYPE, null: true field :description, GraphQL::STRING_TYPE, null: true
markdown_field :description_html, null: true
field :title, GraphQL::STRING_TYPE, null: false field :title, GraphQL::STRING_TYPE, null: false
field :color, GraphQL::STRING_TYPE, null: false field :color, GraphQL::STRING_TYPE, null: false
field :text_color, GraphQL::STRING_TYPE, null: false field :text_color, GraphQL::STRING_TYPE, null: false
......
...@@ -15,7 +15,9 @@ module Types ...@@ -15,7 +15,9 @@ module Types
field :id, GraphQL::ID_TYPE, null: false field :id, GraphQL::ID_TYPE, null: false
field :iid, GraphQL::STRING_TYPE, null: false field :iid, GraphQL::STRING_TYPE, null: false
field :title, GraphQL::STRING_TYPE, null: false field :title, GraphQL::STRING_TYPE, null: false
markdown_field :title_html, null: true
field :description, GraphQL::STRING_TYPE, null: true field :description, GraphQL::STRING_TYPE, null: true
markdown_field :description_html, null: true
field :state, MergeRequestStateEnum, null: false field :state, MergeRequestStateEnum, null: false
field :created_at, Types::TimeType, null: false field :created_at, Types::TimeType, null: false
field :updated_at, Types::TimeType, null: false field :updated_at, Types::TimeType, null: false
......
...@@ -12,6 +12,7 @@ module Types ...@@ -12,6 +12,7 @@ module Types
field :full_path, GraphQL::ID_TYPE, null: false field :full_path, GraphQL::ID_TYPE, null: false
field :description, GraphQL::STRING_TYPE, null: true field :description, GraphQL::STRING_TYPE, null: true
markdown_field :description_html, null: true
field :visibility, GraphQL::STRING_TYPE, null: true field :visibility, GraphQL::STRING_TYPE, null: true
field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true, method: :lfs_enabled? field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true, method: :lfs_enabled?
field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true
......
...@@ -35,6 +35,8 @@ module Types ...@@ -35,6 +35,8 @@ module Types
method: :note, method: :note,
description: "The content note itself" description: "The content note itself"
markdown_field :body_html, null: true, method: :note
field :created_at, Types::TimeType, null: false field :created_at, Types::TimeType, null: false
field :updated_at, Types::TimeType, null: false field :updated_at, Types::TimeType, null: false
field :discussion, Types::Notes::DiscussionType, null: true, description: "The discussion this note is a part of" field :discussion, Types::Notes::DiscussionType, null: true, description: "The discussion this note is a part of"
......
...@@ -17,6 +17,7 @@ module Types ...@@ -17,6 +17,7 @@ module Types
field :name, GraphQL::STRING_TYPE, null: false field :name, GraphQL::STRING_TYPE, null: false
field :description, GraphQL::STRING_TYPE, null: true field :description, GraphQL::STRING_TYPE, null: true
markdown_field :description_html, null: true
field :tag_list, GraphQL::STRING_TYPE, null: true field :tag_list, GraphQL::STRING_TYPE, null: true
......
...@@ -278,7 +278,7 @@ module MarkupHelper ...@@ -278,7 +278,7 @@ module MarkupHelper
def prepare_for_rendering(html, context = {}) def prepare_for_rendering(html, context = {})
return '' unless html.present? return '' unless html.present?
context.merge!( context.reverse_merge!(
current_user: (current_user if defined?(current_user)), current_user: (current_user if defined?(current_user)),
# RelativeLinkFilter # RelativeLinkFilter
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module Clusters module Clusters
module Applications module Applications
class Knative < ApplicationRecord class Knative < ApplicationRecord
VERSION = '0.5.0'.freeze VERSION = '0.6.0'.freeze
REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze
METRICS_CONFIG = 'https://storage.googleapis.com/triggermesh-charts/istio-metrics.yaml'.freeze METRICS_CONFIG = 'https://storage.googleapis.com/triggermesh-charts/istio-metrics.yaml'.freeze
FETCH_IP_ADDRESS_DELAY = 30.seconds FETCH_IP_ADDRESS_DELAY = 30.seconds
......
...@@ -55,8 +55,6 @@ class Project < ApplicationRecord ...@@ -55,8 +55,6 @@ class Project < ApplicationRecord
VALID_MIRROR_PORTS = [22, 80, 443].freeze VALID_MIRROR_PORTS = [22, 80, 443].freeze
VALID_MIRROR_PROTOCOLS = %w(http https ssh git).freeze VALID_MIRROR_PROTOCOLS = %w(http https ssh git).freeze
ignore_column :import_status, :import_jid, :import_error
cache_markdown_field :description, pipeline: :description cache_markdown_field :description, pipeline: :description
delegate :feature_available?, :builds_enabled?, :wiki_enabled?, delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
......
...@@ -297,6 +297,7 @@ class ProjectPolicy < BasePolicy ...@@ -297,6 +297,7 @@ class ProjectPolicy < BasePolicy
end end
rule { (mirror_available & can?(:admin_project)) | admin }.enable :admin_remote_mirror rule { (mirror_available & can?(:admin_project)) | admin }.enable :admin_remote_mirror
rule { can?(:push_code) }.enable :admin_tag
rule { archived }.policy do rule { archived }.policy do
prevent :push_code prevent :push_code
......
# frozen_string_literal: true
module Git
class WikiPushService < ::BaseService
def execute
# This is used in EE
end
end
end
...@@ -4,6 +4,14 @@ module Lfs ...@@ -4,6 +4,14 @@ module Lfs
# Usage: Calling `new_file` check to see if a file should be in LFS and # Usage: Calling `new_file` check to see if a file should be in LFS and
# return a transformed result with `content` and `encoding` to commit. # return a transformed result with `content` and `encoding` to commit.
# #
# The `repository` passed to the initializer can be a Repository or
# a DesignManagement::Repository (an EE-specific class that inherits
# from Repository).
#
# The `repository_type` property will be one of the types named in
# `Gitlab::GlRepository.types`, and is recorded on the `LfsObjectsProject`
# in order to identify the repository location of the blob.
#
# For LFS an LfsObject linked to the project is stored and an LFS # For LFS an LfsObject linked to the project is stored and an LFS
# pointer returned. If the file isn't in LFS the untransformed content # pointer returned. If the file isn't in LFS the untransformed content
# is returned to save in the commit. # is returned to save in the commit.
...@@ -52,7 +60,7 @@ module Lfs ...@@ -52,7 +60,7 @@ module Lfs
end end
def cached_attributes def cached_attributes
@cached_attributes ||= Gitlab::Git::AttributesAtRefParser.new(repository, branch_name) @cached_attributes ||= repository.attributes_at(branch_name)
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
......
...@@ -5,10 +5,12 @@ module Users ...@@ -5,10 +5,12 @@ module Users
delegate :user_default_internal_regex_enabled?, delegate :user_default_internal_regex_enabled?,
:user_default_internal_regex_instance, :user_default_internal_regex_instance,
to: :'Gitlab::CurrentSettings.current_application_settings' to: :'Gitlab::CurrentSettings.current_application_settings'
attr_reader :identity_params
def initialize(current_user, params = {}) def initialize(current_user, params = {})
@current_user = current_user @current_user = current_user
@params = params.dup @params = params.dup
@identity_params = params.slice(*identity_attributes)
end end
def execute(skip_authorization: false) def execute(skip_authorization: false)
...@@ -26,10 +28,8 @@ module Users ...@@ -26,10 +28,8 @@ module Users
end end
end end
identity_attrs = params.slice(*identity_params) unless identity_params.empty?
user.identities.build(identity_params)
unless identity_attrs.empty?
user.identities.build(identity_attrs)
end end
user user
...@@ -37,7 +37,7 @@ module Users ...@@ -37,7 +37,7 @@ module Users
private private
def identity_params def identity_attributes
[:extern_uid, :provider] [:extern_uid, :provider]
end end
......
...@@ -3,11 +3,13 @@ ...@@ -3,11 +3,13 @@
module Users module Users
class UpdateService < BaseService class UpdateService < BaseService
include NewUserNotifier include NewUserNotifier
attr_reader :user, :identity_params
def initialize(current_user, params = {}) def initialize(current_user, params = {})
@current_user = current_user @current_user = current_user
@user = params.delete(:user) @user = params.delete(:user)
@status_params = params.delete(:status) @status_params = params.delete(:status)
@identity_params = params.slice(*identity_attributes)
@params = params.dup @params = params.dup
end end
...@@ -15,8 +17,8 @@ module Users ...@@ -15,8 +17,8 @@ module Users
yield(@user) if block_given? yield(@user) if block_given?
user_exists = @user.persisted? user_exists = @user.persisted?
assign_attributes assign_attributes
assign_identity
if @user.save(validate: validate) && update_status if @user.save(validate: validate) && update_status
notify_success(user_exists) notify_success(user_exists)
...@@ -55,7 +57,18 @@ module Users ...@@ -55,7 +57,18 @@ module Users
params.reject! { |key, _| read_only.include?(key.to_sym) } params.reject! { |key, _| read_only.include?(key.to_sym) }
end end
@user.assign_attributes(params) unless params.empty? @user.assign_attributes(params.except(*identity_attributes)) unless params.empty? # rubocop: disable CodeReuse/ActiveRecord
end
def assign_identity
return unless identity_params.present?
identity = user.identities.find_or_create_by(provider: identity_params[:provider]) # rubocop: disable CodeReuse/ActiveRecord
identity.update(identity_params)
end
def identity_attributes
[:provider, :extern_uid]
end end
end end
end end
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
= f.text_field :name, class: "form-control top qa-new-user-name js-block-emoji js-validate-length", :data => { :max_length => max_name_length, :max_length_message => s_("SignUp|Name is too long (maximum is %{max_length} characters).") % { max_length: max_name_length } }, required: true, title: _("This field is required.") = f.text_field :name, class: "form-control top qa-new-user-name js-block-emoji js-validate-length", :data => { :max_length => max_name_length, :max_length_message => s_("SignUp|Name is too long (maximum is %{max_length} characters).") % { max_length: max_name_length } }, required: true, title: _("This field is required.")
.username.form-group .username.form-group
= f.label :username, class: 'label-bold' = f.label :username, class: 'label-bold'
= f.text_field :username, class: "form-control middle qa-new-user-username js-block-emoji js-validate-length", :data => { :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length } }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.") = f.text_field :username, class: "form-control middle qa-new-user-username js-block-emoji js-validate-length js-validate-username", :data => { :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length } }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
%p.validation-error.field-validation.hide= _('Username is already taken.') %p.validation-error.gl-field-error-ignore.field-validation.hide= _('Username is already taken.')
%p.validation-success.field-validation.hide= _('Username is available.') %p.validation-success.gl-field-error-ignore.field-validation.hide= _('Username is available.')
%p.validation-pending.field-validation.hide= _('Checking username availability...') %p.validation-pending.gl-field-error-ignore.field-validation.hide= _('Checking username availability...')
.form-group .form-group
= f.label :email, class: 'label-bold' = f.label :email, class: 'label-bold'
= f.email_field :email, class: "form-control middle qa-new-user-email", required: true, title: _("Please provide a valid email address.") = f.email_field :email, class: "form-control middle qa-new-user-email", required: true, title: _("Please provide a valid email address.")
......
...@@ -26,10 +26,8 @@ ...@@ -26,10 +26,8 @@
.row-fixed-content.controls.flex-row .row-fixed-content.controls.flex-row
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name] = render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
- if can?(current_user, :push_code, @project) - if can?(current_user, :admin_tag, @project)
= link_to edit_project_tag_release_path(@project, tag.name), class: 'btn btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do = link_to edit_project_tag_release_path(@project, tag.name), class: 'btn btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
= icon("pencil") = icon("pencil")
- if can?(current_user, :admin_project, @project)
= link_to project_tag_path(@project, tag.name), class: "btn btn-remove remove-row has-tooltip prepend-left-10 #{protected_tag?(@project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: tag.name }, container: 'body' }, remote: true do = link_to project_tag_path(@project, tag.name), class: "btn btn-remove remove-row has-tooltip prepend-left-10 #{protected_tag?(@project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: tag.name }, container: 'body' }, remote: true do
= icon("trash-o") = icon("trash-o")
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
- tags_sort_options_hash.each do |value, title| - tags_sort_options_hash.each do |value, title|
%li %li
= link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value) = link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value)
- if can?(current_user, :push_code, @project) - if can?(current_user, :admin_tag, @project)
= link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn' do = link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn' do
= s_('TagsPage|New tag') = s_('TagsPage|New tag')
= link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn d-none d-sm-inline-block has-tooltip' do = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn d-none d-sm-inline-block has-tooltip' do
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
= s_("TagsPage|Can't find HEAD commit for this tag") = s_("TagsPage|Can't find HEAD commit for this tag")
.nav-controls .nav-controls
- if can?(current_user, :push_code, @project) - if can?(current_user, :admin_tag, @project)
= link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
= icon("pencil") = icon("pencil")
= link_to project_tree_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse files') do = link_to project_tree_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse files') do
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
= icon('history') = icon('history')
.btn-container.controls-item .btn-container.controls-item
= render 'projects/buttons/download', project: @project, ref: @tag.name = render 'projects/buttons/download', project: @project, ref: @tag.name
- if can?(current_user, :push_code, @project) && can?(current_user, :admin_project, @project) - if can?(current_user, :admin_tag, @project)
.btn-container.controls-item-full .btn-container.controls-item-full
= link_to project_tag_path(@project, @tag.name), class: "btn btn-remove remove-row has-tooltip #{protected_tag?(@project, @tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: @tag.name } } do = link_to project_tag_path(@project, @tag.name), class: "btn btn-remove remove-row has-tooltip #{protected_tag?(@project, @tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: @tag.name } } do
%i.fa.fa-trash-o %i.fa.fa-trash-o
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
= auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity") = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity")
.user-profile .user-profile
.cover-block.user-cover-block .cover-block.user-cover-block{ class: [('border-bottom' if profile_tabs.empty?)] }
.cover-controls .cover-controls
- if @user == current_user - if @user == current_user
= link_to profile_path, class: 'btn btn-default has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile' do = link_to profile_path, class: 'btn btn-default has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile' do
......
...@@ -2,12 +2,9 @@ ...@@ -2,12 +2,9 @@
class CleanupContainerRepositoryWorker class CleanupContainerRepositoryWorker
include ApplicationWorker include ApplicationWorker
include ExclusiveLeaseGuard
queue_namespace :container_repository queue_namespace :container_repository
LEASE_TIMEOUT = 1.hour
attr_reader :container_repository, :current_user attr_reader :container_repository, :current_user
def perform(current_user_id, container_repository_id, params) def perform(current_user_id, container_repository_id, params)
...@@ -16,12 +13,10 @@ class CleanupContainerRepositoryWorker ...@@ -16,12 +13,10 @@ class CleanupContainerRepositoryWorker
return unless valid? return unless valid?
try_obtain_lease do
Projects::ContainerRepository::CleanupTagsService Projects::ContainerRepository::CleanupTagsService
.new(project, current_user, params) .new(project, current_user, params)
.execute(container_repository) .execute(container_repository)
end end
end
private private
...@@ -32,22 +27,4 @@ class CleanupContainerRepositoryWorker ...@@ -32,22 +27,4 @@ class CleanupContainerRepositoryWorker
def project def project
container_repository&.project container_repository&.project
end end
# For ExclusiveLeaseGuard concern
def lease_key
@lease_key ||= "container_repository:cleanup_tags:#{container_repository.id}"
end
# For ExclusiveLeaseGuard concern
def lease_timeout
LEASE_TIMEOUT
end
# For ExclusiveLeaseGuard concern
def lease_release?
# we don't allow to execute this worker
# more often than LEASE_TIMEOUT
# for given container repository
false
end
end end
...@@ -30,15 +30,17 @@ class PostReceive ...@@ -30,15 +30,17 @@ class PostReceive
private private
def identify_user(post_received)
post_received.identify.tap do |user|
log("Triggered hook for non-existing user \"#{post_received.identifier}\"") unless user
end
end
def process_project_changes(post_received) def process_project_changes(post_received)
changes = [] changes = []
refs = Set.new refs = Set.new
@user = post_received.identify user = identify_user(post_received)
return false unless user
unless @user
log("Triggered hook for non-existing user \"#{post_received.identifier}\"")
return false
end
post_received.enum_for(:changes_refs).with_index do |(oldrev, newrev, ref), index| post_received.enum_for(:changes_refs).with_index do |(oldrev, newrev, ref), index|
service_klass = service_klass =
...@@ -51,7 +53,7 @@ class PostReceive ...@@ -51,7 +53,7 @@ class PostReceive
if service_klass if service_klass
service_klass.new( service_klass.new(
post_received.project, post_received.project,
@user, user,
oldrev: oldrev, oldrev: oldrev,
newrev: newrev, newrev: newrev,
ref: ref, ref: ref,
...@@ -64,7 +66,7 @@ class PostReceive ...@@ -64,7 +66,7 @@ class PostReceive
refs << ref refs << ref
end end
after_project_changes_hooks(post_received, @user, refs.to_a, changes) after_project_changes_hooks(post_received, user, refs.to_a, changes)
end end
def after_project_changes_hooks(post_received, user, refs, changes) def after_project_changes_hooks(post_received, user, refs, changes)
...@@ -76,6 +78,11 @@ class PostReceive ...@@ -76,6 +78,11 @@ class PostReceive
post_received.project.touch(:last_activity_at, :last_repository_updated_at) post_received.project.touch(:last_activity_at, :last_repository_updated_at)
post_received.project.wiki.repository.expire_statistics_caches post_received.project.wiki.repository.expire_statistics_caches
ProjectCacheWorker.perform_async(post_received.project.id, [], [:wiki_size]) ProjectCacheWorker.perform_async(post_received.project.id, [], [:wiki_size])
user = identify_user(post_received)
return false unless user
::Git::WikiPushService.new(post_received.project, user, changes: post_received.enum_for(:changes_refs)).execute
end end
def log(message) def log(message)
......
---
title: Fix Container Scanning job timeout when using the kubernetes executor
merge_request: 29706
author:
type: fixed
---
title: Fix nested lists unnecessary margin
merge_request: 29775
author: Kuba Kopeć
type: fixed
---
title: Remove MySQL support
merge_request: 29790
author:
type: removed
---
title: Allow developers to delete tags
merge_request: 29668
author:
type: changed
---
title: Add token_encrypted column to operations_feature_flags_clients table
merge_request:
author:
type: other
---
title: Fix missing API notification flags for Microsoft Teams
merge_request: 29824
author: Seiji Suenaga
type: fixed
---
title: Add identity information to external authorization requests
merge_request: 29461
author:
type: changed
---
title: Return 400 when deleting tags more often than once per hour.
merge_request: 29448
author:
type: changed
---
title: Fix the signup form's username validation messages not displaying
merge_request: 29678
author: Jiaan Louw
type: fixed
---
title: Fix Double Border in Profile Page
merge_request: 29784
author: Yoginth <@yo>
type: fixed
---
title: Indent collapsible sections
merge_request: 29804
author:
type: other
---
title: Render GFM in GraphQL
merge_request: 29700
author:
type: added
---
title: Expose saml_provider_id in the users API
merge_request: 14045
author:
type: added
---
title: 'Fix favicon path with uploads of object store'
merge_request: 29482
author: Roger Meier
type: fixed
---
title: Knative version bump 0.5 -> 0.6
merge_request: 28798
author: Chris Baumbauer
type: changed
---
title: Cache feature flag names in Redis for a minute
merge_request: 29816
author:
type: performance
---
title: Remove import columns from projects table
merge_request: 29863
author:
type: performance
# frozen_string_literal: true
raise "PostgreSQL is the only supported database from GitLab 12.1" unless
Gitlab::Database.postgresql?
...@@ -80,7 +80,7 @@ def unicode_emoji_regex ...@@ -80,7 +80,7 @@ def unicode_emoji_regex
))x ))x
end end
def lint_commit(commit) def lint_commit(commit) # rubocop:disable Metrics/AbcSize
# For now we'll ignore merge commits, as getting rid of those is a problem # For now we'll ignore merge commits, as getting rid of those is a problem
# separate from enforcing good commit messages. # separate from enforcing good commit messages.
return false if commit.message.start_with?('Merge branch') return false if commit.message.start_with?('Merge branch')
...@@ -114,6 +114,16 @@ def lint_commit(commit) ...@@ -114,6 +114,16 @@ def lint_commit(commit)
) )
end end
# Fail if a suggestion commit is used and squash is not enabled
if commit.message.start_with?('Apply suggestion to') && !gitlab.mr_json['squash']
fail_commit(
commit,
'If you are applying suggestions, squash needs to be enabled in the merge request'
)
failures = true
end
unless subject_starts_with_capital?(subject) unless subject_starts_with_capital?(subject)
fail_commit(commit, 'The commit subject must start with a capital letter') fail_commit(commit, 'The commit subject must start with a capital letter')
failures = true failures = true
......
# frozen_string_literal: true
class AddWikiColumnsToIndexStatus < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :index_statuses, :last_wiki_commit, :binary
add_column :index_statuses, :wiki_indexed_at, :datetime_with_timezone
end
end
# frozen_string_literal: true
class RemoveImportColumnsFromProjects < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def change
remove_column :projects, :import_status, :string
remove_column :projects, :import_jid, :string
remove_column :projects, :import_error, :text
end
end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20190618171120) do ActiveRecord::Schema.define(version: 20190619175843) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -1572,6 +1572,8 @@ ActiveRecord::Schema.define(version: 20190618171120) do ...@@ -1572,6 +1572,8 @@ ActiveRecord::Schema.define(version: 20190618171120) do
t.string "last_commit" t.string "last_commit"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.binary "last_wiki_commit"
t.datetime_with_timezone "wiki_indexed_at"
t.index ["project_id"], name: "index_index_statuses_on_project_id", unique: true, using: :btree t.index ["project_id"], name: "index_index_statuses_on_project_id", unique: true, using: :btree
end end
...@@ -2593,11 +2595,9 @@ ActiveRecord::Schema.define(version: 20190618171120) do ...@@ -2593,11 +2595,9 @@ ActiveRecord::Schema.define(version: 20190618171120) do
t.integer "visibility_level", default: 0, null: false t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false t.boolean "archived", default: false, null: false
t.string "avatar" t.string "avatar"
t.string "import_status"
t.integer "star_count", default: 0, null: false t.integer "star_count", default: 0, null: false
t.string "import_type" t.string "import_type"
t.string "import_source" t.string "import_source"
t.text "import_error"
t.boolean "shared_runners_enabled", default: true, null: false t.boolean "shared_runners_enabled", default: true, null: false
t.string "runners_token" t.string "runners_token"
t.string "build_coverage_regex" t.string "build_coverage_regex"
...@@ -2619,7 +2619,6 @@ ActiveRecord::Schema.define(version: 20190618171120) do ...@@ -2619,7 +2619,6 @@ ActiveRecord::Schema.define(version: 20190618171120) do
t.boolean "only_allow_merge_if_all_discussions_are_resolved" t.boolean "only_allow_merge_if_all_discussions_are_resolved"
t.boolean "printing_merge_request_link_enabled", default: true, null: false t.boolean "printing_merge_request_link_enabled", default: true, null: false
t.integer "auto_cancel_pending_pipelines", default: 1, null: false t.integer "auto_cancel_pending_pipelines", default: 1, null: false
t.string "import_jid"
t.integer "cached_markdown_version" t.integer "cached_markdown_version"
t.text "delete_error" t.text "delete_error"
t.datetime "last_repository_updated_at" t.datetime "last_repository_updated_at"
......
...@@ -42,7 +42,7 @@ The list of `GITLAB_DATABASE_XXX` variables that you can set is: ...@@ -42,7 +42,7 @@ The list of `GITLAB_DATABASE_XXX` variables that you can set is:
Variable | Default value | Overridden by `DATABASE_URL`? Variable | Default value | Overridden by `DATABASE_URL`?
-------- | ------------- | ----------------------------- -------- | ------------- | -----------------------------
`GITLAB_DATABASE_ADAPTER` | `postgresql` (for MySQL use `mysql2`) | Yes `GITLAB_DATABASE_ADAPTER` | `postgresql` | Yes
`GITLAB_DATABASE_DATABASE` | `gitlab_#{ENV['RAILS_ENV']` | Yes `GITLAB_DATABASE_DATABASE` | `gitlab_#{ENV['RAILS_ENV']` | Yes
`GITLAB_DATABASE_USERNAME` | `root` | Yes `GITLAB_DATABASE_USERNAME` | `root` | Yes
`GITLAB_DATABASE_PASSWORD` | None | Yes `GITLAB_DATABASE_PASSWORD` | None | Yes
......
...@@ -489,10 +489,6 @@ work: ...@@ -489,10 +489,6 @@ work:
gitlab-ctl reconfigure gitlab-ctl reconfigure
``` ```
## MySQL replication
MySQL replication is not supported for Geo.
## Troubleshooting ## Troubleshooting
Read the [troubleshooting document](troubleshooting.md). Read the [troubleshooting document](troubleshooting.md).
......
...@@ -432,6 +432,24 @@ gitaly_enabled=false ...@@ -432,6 +432,24 @@ gitaly_enabled=false
When you run `service gitlab restart` Gitaly will be disabled on this When you run `service gitlab restart` Gitaly will be disabled on this
particular machine. particular machine.
## Eliminating NFS altogether
If you are planning to use Gitaly without NFS for your storage needs
and want to eliminate NFS from your environment altogether, there are
a few things that you need to do:
1. Make sure the [`git` user home directory](https://docs.gitlab.com/omnibus/settings/configuration.html#moving-the-home-directory-for-a-user) is on local disk.
1. Configure [database lookup of SSH keys](https://docs.gitlab.com/ce/administration/operations/fast_ssh_key_lookup.html)
to eliminate the need for a shared authorized_keys file.
1. Configure [object storage for job artifacts](https://docs.gitlab.com/ce/administration/job_artifacts.html#using-object-storage)
including [live tracing](https://docs.gitlab.com/ce/administration/job_traces.html#new-live-trace-architecture).
1. Configure [object storage for LFS objects](https://docs.gitlab.com/ce/workflow/lfs/lfs_administration.html#storing-lfs-objects-in-remote-object-storage).
1. Configure [object storage for uploads](https://docs.gitlab.com/ce/administration/uploads.html#using-object-storage-core-only).
NOTE: **Note:** One current feature of GitLab still requires a shared directory (NFS): [GitLab Pages](../../user/project/pages/index.md).
There is [work in progress](https://gitlab.com/gitlab-org/gitlab-pages/issues/196)
to eliminate the need for NFS to support GitLab Pages.
## Troubleshooting Gitaly in production ## Troubleshooting Gitaly in production
Since GitLab 11.6, Gitaly comes with a command-line tool called Since GitLab 11.6, Gitaly comes with a command-line tool called
......
...@@ -33,7 +33,6 @@ Learn how to install, configure, update, and maintain your GitLab instance. ...@@ -33,7 +33,6 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Install](../install/README.md): Requirements, directory structures, and installation methods. - [Install](../install/README.md): Requirements, directory structures, and installation methods.
- [Database load balancing](database_load_balancing.md): Distribute database queries among multiple database servers. **[STARTER ONLY]** - [Database load balancing](database_load_balancing.md): Distribute database queries among multiple database servers. **[STARTER ONLY]**
- [Omnibus support for external MySQL DB](https://docs.gitlab.com/omnibus/settings/database.html#using-a-mysql-database-management-server-enterprise-edition-only): Omnibus package supports configuring an external MySQL database. **[STARTER ONLY]**
- [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only) **[STARTER ONLY]** - [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only) **[STARTER ONLY]**
- [High Availability](high_availability/README.md): Configure multiple servers for scaling or high availability. - [High Availability](high_availability/README.md): Configure multiple servers for scaling or high availability.
- [Installing GitLab HA on Amazon Web Services (AWS)](../install/aws/index.md): Set up GitLab High Availability on Amazon AWS. - [Installing GitLab HA on Amazon Web Services (AWS)](../install/aws/index.md): Set up GitLab High Availability on Amazon AWS.
......
...@@ -35,6 +35,7 @@ The following API resources are available in the project context: ...@@ -35,6 +35,7 @@ The following API resources are available in the project context:
| [Environments](environments.md) | `/projects/:id/environments` | | [Environments](environments.md) | `/projects/:id/environments` |
| [Events](events.md) | `/projects/:id/events` (also available for users and standalone) | | [Events](events.md) | `/projects/:id/events` (also available for users and standalone) |
| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) | | [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
| [Issues Statistics](issues_statistics.md) | `/projects/:id/issues_statistics` (also available for groups and standalone) |
| [Issue boards](boards.md) | `/projects/:id/boards` | | [Issue boards](boards.md) | `/projects/:id/boards` |
| [Issue links](issue_links.md) **[STARTER]** | `/projects/:id/issues/.../links` | | [Issue links](issue_links.md) **[STARTER]** | `/projects/:id/issues/.../links` |
| [Jobs](jobs.md) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` | | [Jobs](jobs.md) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` |
...@@ -92,6 +93,7 @@ The following API resources are available in the group context: ...@@ -92,6 +93,7 @@ The following API resources are available in the group context:
| [Group-level variables](group_level_variables.md) | `/groups/:id/variables` | | [Group-level variables](group_level_variables.md) | `/groups/:id/variables` |
| [Group milestones](group_milestones.md) | `/groups/:id/milestones` | | [Group milestones](group_milestones.md) | `/groups/:id/milestones` |
| [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) | | [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) |
| [Issues Statistics](issues_statistics.md) | `/groups/:id/issues_statistics` (also available for projects and standalone) |
| [Members](members.md) | `/groups/:id/members` (also available for projects) | | [Members](members.md) | `/groups/:id/members` (also available for projects) |
| [Merge requests](merge_requests.md) | `/groups/:id/merge_requests` (also available for projects and standalone) | | [Merge requests](merge_requests.md) | `/groups/:id/merge_requests` (also available for projects and standalone) |
| [Notes](notes.md) (comments) | `/groups/:id/epics/.../notes` (also available for projects) | | [Notes](notes.md) (comments) | `/groups/:id/epics/.../notes` (also available for projects) |
...@@ -116,6 +118,7 @@ The following API resources are available outside of project and group contexts ...@@ -116,6 +118,7 @@ The following API resources are available outside of project and group contexts
| [Geo Nodes](geo_nodes.md) **[PREMIUM ONLY]** | `/geo_nodes` | | [Geo Nodes](geo_nodes.md) **[PREMIUM ONLY]** | `/geo_nodes` |
| [Import repository from GitHub](import.md) | `/import/github` | | [Import repository from GitHub](import.md) | `/import/github` |
| [Issues](issues.md) | `/issues` (also available for groups and projects) | | [Issues](issues.md) | `/issues` (also available for groups and projects) |
| [Issues Statistics](issues_statistics.md) | `/issues_statistics` (also available for groups and projects) |
| [Keys](keys.md) | `/keys` | | [Keys](keys.md) | `/keys` |
| [License](license.md) **[CORE ONLY]** | `/license` | | [License](license.md) **[CORE ONLY]** | `/license` |
| [Markdown](markdown.md) | `/markdown` | | [Markdown](markdown.md) | `/markdown` |
......
...@@ -145,6 +145,9 @@ DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name ...@@ -145,6 +145,9 @@ DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0" curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0"
``` ```
This action does not delete blobs. In order to delete them and recycle disk space,
[run the garbage collection](https://docs.gitlab.com/omnibus/maintenance/README.html#removing-unused-layers-not-referenced-by-manifests).
## Delete repository tags in bulk ## Delete repository tags in bulk
Delete repository tags in bulk based on given criteria. Delete repository tags in bulk based on given criteria.
...@@ -174,6 +177,8 @@ This API call performs the following operations: ...@@ -174,6 +177,8 @@ This API call performs the following operations:
These operations are executed asynchronously and it might These operations are executed asynchronously and it might
take time to get executed. You can run this at most take time to get executed. You can run this at most
once an hour for a given container repository. once an hour for a given container repository.
This action does not delete blobs. In order to delete them and recycle disk space,
[run the garbage collection](https://docs.gitlab.com/omnibus/maintenance/README.html#removing-unused-layers-not-referenced-by-manifests).
NOTE: **Note:** NOTE: **Note:**
Due to a [Docker Distribution deficiency](https://gitlab.com/gitlab-org/gitlab-ce/issues/21405), Due to a [Docker Distribution deficiency](https://gitlab.com/gitlab-org/gitlab-ce/issues/21405),
......
...@@ -1023,6 +1023,8 @@ Parameters: ...@@ -1023,6 +1023,8 @@ Parameters:
| Parameter | Type | Required | Description | | Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` | | `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch |
| `push_events` | boolean | false | Enable notifications for push events | | `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events | | `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | | `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
## List users ## List users
Active users = Total accounts - Blocked users
Get a list of users. Get a list of users.
This function takes pagination parameters `page` and `per_page` to restrict the list of users. This function takes pagination parameters `page` and `per_page` to restrict the list of users.
...@@ -257,7 +259,8 @@ Parameters: ...@@ -257,7 +259,8 @@ Parameters:
"two_factor_enabled": true, "two_factor_enabled": true,
"external": false, "external": false,
"private_profile": false, "private_profile": false,
"highest_role":10 "shared_runners_minutes_limit": 133
"extra_shared_runners_minutes_limit": 133
} }
``` ```
...@@ -290,6 +293,7 @@ Parameters: ...@@ -290,6 +293,7 @@ Parameters:
- `projects_limit` (optional) - Number of projects user can create - `projects_limit` (optional) - Number of projects user can create
- `extern_uid` (optional) - External UID - `extern_uid` (optional) - External UID
- `provider` (optional) - External provider name - `provider` (optional) - External provider name
- `group_id_for_saml` (optional) - ID of group where SAML has been configured
- `bio` (optional) - User's biography - `bio` (optional) - User's biography
- `location` (optional) - User's location - `location` (optional) - User's location
- `public_email` (optional) - The public email of the user - `public_email` (optional) - The public email of the user
...@@ -299,6 +303,8 @@ Parameters: ...@@ -299,6 +303,8 @@ Parameters:
- `external` (optional) - Flags the user as external - true or false(default) - `external` (optional) - Flags the user as external - true or false(default)
- `avatar` (optional) - Image file for user's avatar - `avatar` (optional) - Image file for user's avatar
- `private_profile` (optional) - User's profile is private - true or false - `private_profile` (optional) - User's profile is private - true or false
- `shared_runners_minutes_limit` (optional) - Pipeline minutes quota for this user
- `extra_shared_runners_minutes_limit` (optional) - Extra pipeline minutes quota for this user
## User modification ## User modification
...@@ -322,6 +328,7 @@ Parameters: ...@@ -322,6 +328,7 @@ Parameters:
- `projects_limit` - Limit projects each user can create - `projects_limit` - Limit projects each user can create
- `extern_uid` - External UID - `extern_uid` - External UID
- `provider` - External provider name - `provider` - External provider name
- `group_id_for_saml` (optional) - ID of group where SAML has been configured
- `bio` - User's biography - `bio` - User's biography
- `location` (optional) - User's location - `location` (optional) - User's location
- `public_email` (optional) - The public email of the user - `public_email` (optional) - The public email of the user
...@@ -329,6 +336,8 @@ Parameters: ...@@ -329,6 +336,8 @@ Parameters:
- `can_create_group` (optional) - User can create groups - true or false - `can_create_group` (optional) - User can create groups - true or false
- `skip_reconfirmation` (optional) - Skip reconfirmation - true or false (default) - `skip_reconfirmation` (optional) - Skip reconfirmation - true or false (default)
- `external` (optional) - Flags the user as external - true or false(default) - `external` (optional) - Flags the user as external - true or false(default)
- `shared_runners_minutes_limit` (optional) - Pipeline minutes quota for this user
- `extra_shared_runners_minutes_limit` (optional) - Extra pipeline minutes quota for this user
- `avatar` (optional) - Image file for user's avatar - `avatar` (optional) - Image file for user's avatar
- `private_profile` (optional) - User's profile is private - true or false - `private_profile` (optional) - User's profile is private - true or false
...@@ -1150,8 +1159,6 @@ settings page. ...@@ -1150,8 +1159,6 @@ settings page.
POST /users/:user_id/impersonation_tokens POST /users/:user_id/impersonation_tokens
``` ```
Parameters:
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `user_id` | integer | yes | The ID of the user | | `user_id` | integer | yes | The ID of the user |
......
...@@ -139,6 +139,20 @@ The union of A, B, and C is (1, 4) and (6, 7). Therefore, the total running time ...@@ -139,6 +139,20 @@ The union of A, B, and C is (1, 4) and (6, 7). Therefore, the total running time
(4 - 1) + (7 - 6) => 4 (4 - 1) + (7 - 6) => 4
``` ```
### Expanding and collapsing job log sections
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/14664) in GitLab
> 12.0.
Job logs are divided into sections that can be collapsed or expanded.
In the following example:
- Two sections are expanded and can be collapsed.
- One section is collapsed and can be expanded.
![Collapsible sections](img/collapsible_log.png)
## Configuring pipelines ## Configuring pipelines
Pipelines, and their component jobs and stages, are defined in the [`.gitlab-ci.yml`](yaml/README.md) file for each project. Pipelines, and their component jobs and stages, are defined in the [`.gitlab-ci.yml`](yaml/README.md) file for each project.
......
...@@ -149,7 +149,7 @@ Component statuses are linked to configuration documentation for each component. ...@@ -149,7 +149,7 @@ Component statuses are linked to configuration documentation for each component.
| [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | [][pgbouncer-exporter-omnibus] | [][pgbouncer-exporter-charts] | [][pgbouncer-exporter-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | | [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | [][pgbouncer-exporter-omnibus] | [][pgbouncer-exporter-charts] | [][pgbouncer-exporter-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [GitLab Monitor](#gitlab-monitor) | Generates a variety of GitLab metrics | [][gitlab-monitor-omnibus] | [][gitab-monitor-charts] | [][gitab-monitor-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | | [GitLab Monitor](#gitlab-monitor) | Generates a variety of GitLab metrics | [][gitlab-monitor-omnibus] | [][gitab-monitor-charts] | [][gitab-monitor-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | [][node-exporter-omnibus] | [][node-exporter-charts] | [][node-exporter-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | | [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | [][node-exporter-omnibus] | [][node-exporter-charts] | [][node-exporter-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [Mattermost](#mattermost) | Open-source Slack alternative | [][mattermost-omnibus] | [][mattermost-charts] | [][mattermost-charts] | [](../user/project/integrations/mattermost_slash_commands.md#manual-configuration), [](../user/project/integrations/mattermost.html) | ❌ | ❌ | CE & EE | | [Mattermost](#mattermost) | Open-source Slack alternative | [][mattermost-omnibus] | [][mattermost-charts] | [][mattermost-charts] | [](../user/project/integrations/mattermost.md) | ❌ | ❌ | CE & EE |
| [MinIO](#minio) | Object storage service | [][minio-omnibus] | [][minio-charts] | [][minio-charts] | [](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | ❌ | [][minio-gdk] | CE & EE | | [MinIO](#minio) | Object storage service | [][minio-omnibus] | [][minio-charts] | [][minio-charts] | [](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | ❌ | [][minio-gdk] | CE & EE |
| [Runner](#gitlab-runner) | Executes GitLab CI jobs | [][runner-omnibus] | [][runner-charts] | [][runner-charts] | [](../user/gitlab_com/index.md#shared-runners) | [][runner-source] | [][runner-gdk] | CE & EE | | [Runner](#gitlab-runner) | Executes GitLab CI jobs | [][runner-omnibus] | [][runner-charts] | [][runner-charts] | [](../user/gitlab_com/index.md#shared-runners) | [][runner-source] | [][runner-gdk] | CE & EE |
| [Database Migrations](#database-migrations) | Database migrations | [][database-migrations-omnibus] | [][database-migrations-charts] | [][database-migrations-charts] | ✅ | [][database-migrations-source] | ✅ | CE & EE | | [Database Migrations](#database-migrations) | Database migrations | [][database-migrations-omnibus] | [][database-migrations-charts] | [][database-migrations-charts] | ✅ | [][database-migrations-source] | ✅ | CE & EE |
...@@ -695,7 +695,7 @@ We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/ha ...@@ -695,7 +695,7 @@ We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/ha
[runner-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/runner.md [runner-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/runner.md
[database-migrations-omnibus]: https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration [database-migrations-omnibus]: https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration
[database-migrations-charts]: https://docs.gitlab.com/charts/charts/gitlab/migrations/ [database-migrations-charts]: https://docs.gitlab.com/charts/charts/gitlab/migrations/
[database-migrations-source]: ../update/upgrading_from_source.md#14-install-libs-migrations-etc [database-migrations-source]: ../update/upgrading_from_source.md#13-install-libs-migrations-etc
[certificate-management-omnibus]: https://docs.gitlab.com/omnibus/settings/ssl.html [certificate-management-omnibus]: https://docs.gitlab.com/omnibus/settings/ssl.html
[certificate-management-charts]: https://docs.gitlab.com/charts/installation/tls.html [certificate-management-charts]: https://docs.gitlab.com/charts/installation/tls.html
[certificate-management-source]: ../install/installation.md#using-https [certificate-management-source]: ../install/installation.md#using-https
......
...@@ -77,6 +77,9 @@ Or: ...@@ -77,6 +77,9 @@ Or:
hello = _("Hello world!") hello = _("Hello world!")
``` ```
NOTE: **Note:** Messages in the API (`lib/api/` or `app/graphql`) do
not need to be externalised.
### HAML files ### HAML files
Given the following content in HAML: Given the following content in HAML:
......
...@@ -80,30 +80,6 @@ There are a few environment flags you can pass to change how projects are seeded ...@@ -80,30 +80,6 @@ There are a few environment flags you can pass to change how projects are seeded
- `LARGE_PROJECTS`: defaults to false. If set will clone 6 large projects to help with testing. - `LARGE_PROJECTS`: defaults to false. If set will clone 6 large projects to help with testing.
- `FORK`: defaults to false. If set to `true` will fork `torvalds/linux` five times. Can also be set to an existing project full_path and it will fork that instead. - `FORK`: defaults to false. If set to `true` will fork `torvalds/linux` five times. Can also be set to an existing project full_path and it will fork that instead.
### Notes for MySQL
Since the seeds would contain various UTF-8 characters, such as emojis or so,
we'll need to make sure that we're using `utf8mb4` for all the encoding
settings and `utf8mb4_unicode_ci` for collation. Please check
[MySQL utf8mb4 support](../install/database_mysql.md#mysql-utf8mb4-support)
Make sure that `config/database.yml` has `encoding: utf8mb4`, too.
Next, we'll need to update the schema to make the indices fit:
``` shell
sed -i 's/limit: 255/limit: 191/g' db/schema.rb
```
Then run the setup script:
``` shell
bundle exec rake setup
```
To make sure that indices still fit. You could find great details in:
[How to support full Unicode in MySQL databases](https://mathiasbynens.be/notes/mysql-utf8mb4)
## Run tests ## Run tests
In order to run the test you can use the following commands: In order to run the test you can use the following commands:
......
...@@ -39,14 +39,6 @@ PostgreSQL you can use the `reset_pk_sequence!` method like so: ...@@ -39,14 +39,6 @@ PostgreSQL you can use the `reset_pk_sequence!` method like so:
reset_pk_sequence!('events') reset_pk_sequence!('events')
``` ```
For MySQL however you need to do run the following:
```ruby
amount = Event.pluck('COALESCE(MAX(id), 1)').first
execute "ALTER TABLE events AUTO_INCREMENT = #{amount}"
```
Failure to reset the primary keys will result in newly created rows starting Failure to reset the primary keys will result in newly created rows starting
with an ID value of 1. Depending on the existing data this can then lead to with an ID value of 1. Depending on the existing data this can then lead to
duplicate key constraints from popping up, preventing users from creating new duplicate key constraints from popping up, preventing users from creating new
......
...@@ -247,7 +247,7 @@ module QA ...@@ -247,7 +247,7 @@ module QA
[@new_label_same_scope, @new_label_different_scope].each do |label| [@new_label_same_scope, @new_label_different_scope].each do |label|
Resource::Label.fabricate_via_api! do |l| Resource::Label.fabricate_via_api! do |l|
l.project = issue.project.id l.project = issue.project
l.title = label l.title = label
end end
end end
...@@ -414,7 +414,7 @@ def api_get_path ...@@ -414,7 +414,7 @@ def api_get_path
end end
def api_post_path def api_post_path
"/projects/#{project}/labels" "/projects/#{project.id}/labels"
end end
def api_post_body def api_post_body
......
This diff is collapsed.
...@@ -293,10 +293,9 @@ sudo adduser --disabled-login --gecos 'GitLab' git ...@@ -293,10 +293,9 @@ sudo adduser --disabled-login --gecos 'GitLab' git
## 6. Database ## 6. Database
We recommend using a PostgreSQL database. For MySQL, see the [MySQL setup guide](database_mysql.md).
NOTE: **Note:** NOTE: **Note:**
Because we need to make use of extensions and concurrent index removal, you need at least PostgreSQL 9.2. Starting from GitLab 12.1, only PostgreSQL is supported. Because we need to make
use of extensions and concurrent index removal, you need at least PostgreSQL 9.2.
1. Install the database packages: 1. Install the database packages:
...@@ -502,13 +501,8 @@ If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional ste ...@@ -502,13 +501,8 @@ If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional ste
### Configure GitLab DB Settings ### Configure GitLab DB Settings
```sh ```sh
# PostgreSQL only:
sudo -u git cp config/database.yml.postgresql config/database.yml sudo -u git cp config/database.yml.postgresql config/database.yml
# MySQL only:
sudo -u git cp config/database.yml.mysql config/database.yml
# PostgreSQL only:
# Remove host, username, and password lines from config/database.yml. # Remove host, username, and password lines from config/database.yml.
# Once modified, the `production` settings will be as follows: # Once modified, the `production` settings will be as follows:
# #
...@@ -520,7 +514,7 @@ sudo -u git cp config/database.yml.mysql config/database.yml ...@@ -520,7 +514,7 @@ sudo -u git cp config/database.yml.mysql config/database.yml
# #
sudo -u git -H editor config/database.yml sudo -u git -H editor config/database.yml
# MySQL and remote PostgreSQL only: # Remote PostgreSQL only:
# Update username/password in config/database.yml. # Update username/password in config/database.yml.
# You only need to adapt the production settings (first part). # You only need to adapt the production settings (first part).
# If you followed the database guide then please do as follows: # If you followed the database guide then please do as follows:
...@@ -528,7 +522,6 @@ sudo -u git -H editor config/database.yml ...@@ -528,7 +522,6 @@ sudo -u git -H editor config/database.yml
# You can keep the double quotes around the password # You can keep the double quotes around the password
sudo -u git -H editor config/database.yml sudo -u git -H editor config/database.yml
# PostgreSQL and MySQL:
# Make config/database.yml readable to git only # Make config/database.yml readable to git only
sudo -u git -H chmod o-rwx config/database.yml sudo -u git -H chmod o-rwx config/database.yml
``` ```
...@@ -544,11 +537,7 @@ Make sure you have `bundle` (run `bundle -v`): ...@@ -544,11 +537,7 @@ Make sure you have `bundle` (run `bundle -v`):
- `< 2.x`. - `< 2.x`.
```sh ```sh
# For PostgreSQL (note, the option says "without ... mysql")
sudo -u git -H bundle install --deployment --without development test mysql aws kerberos sudo -u git -H bundle install --deployment --without development test mysql aws kerberos
# Or if you use MySQL (note, the option says "without ... postgres")
sudo -u git -H bundle install --deployment --without development test postgres aws kerberos
``` ```
NOTE: **Note:** NOTE: **Note:**
......
...@@ -104,32 +104,10 @@ installation (e.g. the number of users, projects, etc). ...@@ -104,32 +104,10 @@ installation (e.g. the number of users, projects, etc).
We currently support the following databases: We currently support the following databases:
- PostgreSQL (highly recommended) - PostgreSQL
- MySQL/MariaDB (strongly discouraged, not all GitLab features are supported, no support for [MySQL/MariaDB GTID](https://mariadb.com/kb/en/mariadb/gtid/))
Support for MySQL was removed in GitLab 12.1. Existing users using GitLab with
We highly recommend the use of PostgreSQL instead of MySQL/MariaDB as not all MySQL/MariaDB are advised to [migrate to PostgreSQL](../update/mysql_to_postgresql.md) before upgrading.
features of GitLab work with MySQL/MariaDB:
1. MySQL support for subgroups was [dropped with GitLab 9.3][post].
See [issue #30472][30472] for more information.
1. Geo does [not support MySQL](../administration/geo/replication/database.md). This means no supported Disaster Recovery solution if using MySQL. **[PREMIUM ONLY]**
1. [Zero downtime migrations](../update/README.md#upgrading-without-downtime) do not work with MySQL.
1. [Database load balancing](../administration/database_load_balancing.md) is
supported only for PostgreSQL. **[PREMIUM ONLY]**
1. GitLab [optimizes the loading of dashboard events](https://gitlab.com/gitlab-org/gitlab-ce/issues/31806) using [PostgreSQL LATERAL JOINs](https://blog.heapanalytics.com/postgresqls-powerful-new-join-type-lateral/).
1. In general, SQL optimized for PostgreSQL may run much slower in MySQL due to
differences in query planners. For example, subqueries that work well in PostgreSQL
may not be [performant in MySQL](https://dev.mysql.com/doc/refman/5.7/en/optimizing-subqueries.html).
1. Binary column index length is limited to 20 bytes. This is accomplished with [a hack](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/initializers/mysql_set_length_for_binary_indexes.rb).
1. MySQL requires a variety of hacks to increase limits on various columns, [for example](https://gitlab.com/gitlab-org/gitlab-ce/issues/49583).
1. [The milestone filter runs slower queries on MySQL](https://gitlab.com/gitlab-org/gitlab-ce/issues/51173#note_99391731).
1. We expect this list to grow over time.
Existing users using GitLab with MySQL/MariaDB are advised to
[migrate to PostgreSQL](../update/mysql_to_postgresql.md) instead.
[30472]: https://gitlab.com/gitlab-org/gitlab-ce/issues/30472
[post]: https://about.gitlab.com/2017/06/22/gitlab-9-3-released/#dropping-support-for-subgroups-in-mysql
### PostgreSQL Requirements ### PostgreSQL Requirements
......
...@@ -194,11 +194,7 @@ from the Omniauth provider's documentation. ...@@ -194,11 +194,7 @@ from the Omniauth provider's documentation.
gem "omniauth-your-auth-provider" gem "omniauth-your-auth-provider"
- If you're using MySQL, install the new Omniauth provider gem by running the following command: - Install the new Omniauth provider gem by running the following command:
sudo -u git -H bundle install --without development test postgres --path vendor/bundle --no-deployment
- If you're using PostgreSQL, install the new Omniauth provider gem by running the following command:
sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment
......
...@@ -936,5 +936,36 @@ A similar strategy can be employed for the remaining features - by removing the ...@@ -936,5 +936,36 @@ A similar strategy can be employed for the remaining features - by removing the
data that cannot be decrypted, GitLab can be brought back into working order, data that cannot be decrypted, GitLab can be brought back into working order,
and the lost data can be manually replaced. and the lost data can be manually replaced.
### Container Registry push failures after restoring from a backup
If you use the [Container Registry](../user/project/container_registry.md), you
may see pushes to the registry fail after restoring your backup on an Omnibus
GitLab instance after restoring the registry data.
These failures will mention permission issues in the registry logs, like:
```
level=error
msg="response completed with error"
err.code=unknown
err.detail="filesystem: mkdir /var/opt/gitlab/gitlab-rails/shared/registry/docker/registry/v2/repositories/...: permission denied"
err.message="unknown error"
```
This is caused by the restore being run as the unprivileged user `git` which was
unable to assign the correct ownership to the registry files during the restore
([issue 62759](https://gitlab.com/gitlab-org/gitlab-ce/issues/62759 "Incorrect permissions on registry filesystem after restore")).
To get your registry working again:
```bash
sudo chown -R registry:registry /var/opt/gitlab/gitlab-rails/shared/registry/docker
```
NOTE: **Note:**
If you have changed the default filesystem location for the registry, you will
want to run the chown against your custom location instead of
`/var/opt/gitlab/gitlab-rails/shared/registry/docker`.
[reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure [reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source [restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
...@@ -149,7 +149,6 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres ...@@ -149,7 +149,6 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres
1. [How to Install GitLab with Omnibus - Video](https://www.youtube.com/watch?v=Q69YaOjqNhg) 1. [How to Install GitLab with Omnibus - Video](https://www.youtube.com/watch?v=Q69YaOjqNhg)
1. [Installing GitLab - Online Course](https://courses.platzi.com/classes/git-gitlab/concepto/part-1/part-3/material/) 1. [Installing GitLab - Online Course](https://courses.platzi.com/classes/git-gitlab/concepto/part-1/part-3/material/)
1. [Using a Non-Packaged PostgreSQL Database](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#using-a-non-packaged-postgresql-database-management-server) 1. [Using a Non-Packaged PostgreSQL Database](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#using-a-non-packaged-postgresql-database-management-server)
1. [Using a MySQL Database](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#using-a-mysql-database-management-server-enterprise-edition-only)
1. [Installing GitLab on Microsoft Azure](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/) 1. [Installing GitLab on Microsoft Azure](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/)
1. [Installing GitLab on Digital Ocean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/) 1. [Installing GitLab on Digital Ocean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/)
......
...@@ -49,8 +49,7 @@ However, for this to work there are the following requirements: ...@@ -49,8 +49,7 @@ However, for this to work there are the following requirements:
- You have to use [post-deployment - You have to use [post-deployment
migrations](../development/post_deployment_migrations.md) (included in migrations](../development/post_deployment_migrations.md) (included in
zero downtime update steps below). zero downtime update steps below).
- You are using PostgreSQL. If you are using MySQL please look at the release - You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported.
post to see if downtime is required.
Most of the time you can safely upgrade from a patch release to the next minor Most of the time you can safely upgrade from a patch release to the next minor
release if the patch release is not the latest. For example, upgrading from release if the patch release is not the latest. For example, upgrading from
...@@ -140,8 +139,6 @@ possible. ...@@ -140,8 +139,6 @@ possible.
- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating - [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating
your database from MySQL to PostgreSQL. your database from MySQL to PostgreSQL.
- [MySQL installation guide](../install/database_mysql.md) contains additional
information about configuring GitLab to work with a MySQL database.
- [Restoring from backup after a failed upgrade](restore_after_failure.md) - [Restoring from backup after a failed upgrade](restore_after_failure.md)
- [Upgrading PostgreSQL Using Slony](upgrading_postgresql_using_slony.md), for - [Upgrading PostgreSQL Using Slony](upgrading_postgresql_using_slony.md), for
upgrading a PostgreSQL database with minimal downtime. upgrading a PostgreSQL database with minimal downtime.
......
--- ---
last_updated: 2019-03-27 last_updated: 2019-06-18
--- ---
# Migrating from MySQL to PostgreSQL # Migrating from MySQL to PostgreSQL
...@@ -9,6 +9,10 @@ migrate it to a PostgreSQL database. ...@@ -9,6 +9,10 @@ migrate it to a PostgreSQL database.
## Requirements ## Requirements
NOTE: **Note:**
Support for MySQL was removed in GitLab 12.1. This procedure should be performed
**before** installing GitLab 12.1.
[pgloader](http://pgloader.io) 3.4.1+ is required. [pgloader](http://pgloader.io) 3.4.1+ is required.
You can install it directly from your distribution, for example in You can install it directly from your distribution, for example in
......
...@@ -13,8 +13,6 @@ You can select the tag in the version dropdown in the top left corner of GitLab ...@@ -13,8 +13,6 @@ You can select the tag in the version dropdown in the top left corner of GitLab
### 0. Backup ### 0. Backup
It's useful to make a backup just in case things go south: It's useful to make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab
user on the database version)
```bash ```bash
cd /home/git/gitlab cd /home/git/gitlab
...@@ -48,12 +46,8 @@ sudo -u git -H git checkout LATEST_TAG -b LATEST_TAG ...@@ -48,12 +46,8 @@ sudo -u git -H git checkout LATEST_TAG -b LATEST_TAG
```bash ```bash
cd /home/git/gitlab cd /home/git/gitlab
# PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment sudo -u git -H bundle install --without development test mysql --deployment
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
# Optional: clean up old gems # Optional: clean up old gems
sudo -u git -H bundle clean sudo -u git -H bundle clean
......
...@@ -4,6 +4,10 @@ comments: false ...@@ -4,6 +4,10 @@ comments: false
# Upgrading Community Edition and Enterprise Edition from source # Upgrading Community Edition and Enterprise Edition from source
NOTE: **Note:**
Users wishing to upgrade to 12.0.0 will have to take some extra steps. See the
version specific upgrade instructions for 12.0.0 for more details.
Make sure you view this update guide from the branch (version) of GitLab you Make sure you view this update guide from the branch (version) of GitLab you
would like to install (e.g., `11.8`. You can select the version in the version would like to install (e.g., `11.8`. You can select the version in the version
dropdown at the top left corner of GitLab (below the menu bar). dropdown at the top left corner of GitLab (below the menu bar).
...@@ -235,29 +239,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION) ...@@ -235,29 +239,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
sudo -u git -H make sudo -u git -H make
``` ```
### 12. Update MySQL permissions ### 12. Update configuration files
If you are using MySQL you need to grant the GitLab user the necessary
permissions on the database:
```bash
mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
```
If you use MySQL with replication, or just have MySQL configured with binary logging,
you will need to also run the following on all of your MySQL servers:
```bash
mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
```
You can make this setting permanent by adding it to your `my.cnf`:
```
log_bin_trust_function_creators=1
```
### 13. Update configuration files
#### New configuration options for `gitlab.yml` #### New configuration options for `gitlab.yml`
...@@ -331,18 +313,13 @@ For Ubuntu 16.04.1 LTS: ...@@ -331,18 +313,13 @@ For Ubuntu 16.04.1 LTS:
sudo systemctl daemon-reload sudo systemctl daemon-reload
``` ```
### 14. Install libs, migrations, etc. ### 13. Install libs, migrations, etc.
```bash ```bash
cd /home/git/gitlab cd /home/git/gitlab
# PostgreSQL installations (note: the line below states '--without mysql')
sudo -u git -H bundle install --deployment --without development test mysql aws kerberos sudo -u git -H bundle install --deployment --without development test mysql aws kerberos
# MySQL installations (note: the line below states '--without postgres')
sudo -u git -H bundle install --deployment --without development test postgres aws kerberos
# Optional: clean up old gems # Optional: clean up old gems
sudo -u git -H bundle clean sudo -u git -H bundle clean
...@@ -360,17 +337,14 @@ sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:c ...@@ -360,17 +337,14 @@ sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:c
sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
``` ```
**MySQL installations**: Run through the `MySQL strings limits` and `Tables and ### 14. Start application
data conversion to utf8mb4` [tasks](../install/database_mysql.md).
### 15. Start application
```bash ```bash
sudo service gitlab start sudo service gitlab start
sudo service nginx restart sudo service nginx restart
``` ```
### 16. Check application status ### 15. Check application status
Check if GitLab and its environment are configured correctly: Check if GitLab and its environment are configured correctly:
...@@ -404,6 +378,20 @@ Example: ...@@ -404,6 +378,20 @@ Example:
Additional instructions here. Additional instructions here.
--> -->
### 12.0.0
In 12.0.0 we made various database related changes. These changes require that
users first upgrade to the latest 11.11 patch release. Once upgraded to 11.11.x,
users can upgrade to 12.x. Failure to do so may result in database migrations
not being applied, which could lead to application errors.
Example 1: you are currently using GitLab 11.11.3, which is the latest patch
release for 11.11.x. You can upgrade as usual to 12.0.0, 12.1.0, etc.
Example 2: you are currently using a version of GitLab 10.x. To upgrade, first
upgrade to 11.11.3. Once upgraded to 11.11.3 you can safely upgrade to 12.0.0
or future versions.
## Things went south? Revert to previous version ## Things went south? Revert to previous version
### 1. Revert the code to the previous version ### 1. Revert the code to the previous version
......
...@@ -89,10 +89,8 @@ are enabled. ...@@ -89,10 +89,8 @@ are enabled.
![Project admin info](img/admin_project_quota_view.png) ![Project admin info](img/admin_project_quota_view.png)
When the pipeline minutes quota for a group is set to a value different than 0, You can see an overview of the pipeline minutes quota of all projects of
the **Pipelines quota** page is available to the group page settings list. a group in the **Usage Quotas** page available to the group page settings list.
You can see there an overview of the pipeline minutes quota of all projects of
the group.
![Group pipelines quota](img/group_pipelines_quota.png) ![Group pipelines quota](img/group_pipelines_quota.png)
......
...@@ -76,13 +76,19 @@ service with this body: ...@@ -76,13 +76,19 @@ service with this body:
{ {
"user_identifier": "jane@acme.org", "user_identifier": "jane@acme.org",
"project_classification_label": "project-label", "project_classification_label": "project-label",
"user_ldap_dn": "CN=Jane Doe,CN=admin,DC=acme" "user_ldap_dn": "CN=Jane Doe,CN=admin,DC=acme",
"identities": [
{ "provider": "ldap", "extern_uid": "CN=Jane Doe,CN=admin,DC=acme" },
{ "provider": "bitbucket", "extern_uid": "2435223452345" }
]
} }
``` ```
The `user_ldap_dn` is optional and is only sent when the user is logged in The `user_ldap_dn` is optional and is only sent when the user is logged in
through LDAP. through LDAP.
`identities` will contain the details of all the identities associated with the user. This will be an empty array if there are no identities associated with the user.
When the external authorization service responds with a status code 200, the When the external authorization service responds with a status code 200, the
user is granted access. When the external service responds with a status code user is granted access. When the external service responds with a status code
401 or 403, the user is denied access. In any case, the request is cached for 6 hours. 401 or 403, the user is denied access. In any case, the request is cached for 6 hours.
......
...@@ -381,6 +381,14 @@ Define project templates at a group level by setting a group as the template sou ...@@ -381,6 +381,14 @@ Define project templates at a group level by setting a group as the template sou
for the group. **[STARTER ONLY]** for the group. **[STARTER ONLY]**
- **Pipelines quota**: Keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group. - **Pipelines quota**: Keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group.
#### Storage usage quota **[STARTER]**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/13294) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0.
A group owner can check the aggregated storage usage for all the project in a group, sub-groups included, in the **Storage** tab of the **Usage Quotas** page available to the group page settings list.
![Group storage usage quota](img/group_storage_usage_quota.png)
## User contribution analysis **[STARTER]** ## User contribution analysis **[STARTER]**
With [GitLab Contribution Analytics](contribution_analytics/index.md), With [GitLab Contribution Analytics](contribution_analytics/index.md),
......
...@@ -5,8 +5,7 @@ type: reference, howto, concepts ...@@ -5,8 +5,7 @@ type: reference, howto, concepts
# Subgroups # Subgroups
NOTE: **Note:** NOTE: **Note:**
[Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2772) in GitLab 9.0. Not available when using MySQL as external [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2772) in GitLab 9.0.
database (support removed in GitLab 9.3 [due to performance reasons](https://gitlab.com/gitlab-org/gitlab-ce/issues/30472#note_27747600)).
Subgroups, also known as nested groups or hierarchical groups, allow you to have up to 20 Subgroups, also known as nested groups or hierarchical groups, allow you to have up to 20
levels of groups. levels of groups.
...@@ -21,16 +20,6 @@ By using subgroups you can do the following: ...@@ -21,16 +20,6 @@ By using subgroups you can do the following:
- **Make it easier to manage people and control visibility.** Give people - **Make it easier to manage people and control visibility.** Give people
different [permissions](../../permissions.md#group-members-permissions) depending on their group [membership](#membership). different [permissions](../../permissions.md#group-members-permissions) depending on their group [membership](#membership).
## Database Requirements
Subgroups are only supported when you use PostgreSQL. Supporting subgroups on MySQL in an
efficient way is not possible due to MySQL's limitations.
See the following links for more information:
- <https://gitlab.com/gitlab-org/gitlab-ce/issues/30472>
- <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10885>
## Overview ## Overview
A group can have many subgroups inside it, and at the same time a group can have A group can have many subgroups inside it, and at the same time a group can have
......
...@@ -95,6 +95,7 @@ The following table depicts the various user permission levels in a project. ...@@ -95,6 +95,7 @@ The following table depicts the various user permission levels in a project.
| Dismiss vulnerability **[ULTIMATE]** | | | ✓ | ✓ | ✓ | | Dismiss vulnerability **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
| Apply code change suggestions | | | ✓ | ✓ | ✓ | | Apply code change suggestions | | | ✓ | ✓ | ✓ |
| Create and edit wiki pages | | | ✓ | ✓ | ✓ | | Create and edit wiki pages | | | ✓ | ✓ | ✓ |
| Rewrite/remove Git tags | | | ✓ | ✓ | ✓ |
| Use environment terminals | | | | ✓ | ✓ | | Use environment terminals | | | | ✓ | ✓ |
| Run Web IDE's Interactive Web Terminals **[ULTIMATE ONLY]** | | | | ✓ | ✓ | | Run Web IDE's Interactive Web Terminals **[ULTIMATE ONLY]** | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ | | Add new team members | | | | ✓ | ✓ |
...@@ -102,7 +103,6 @@ The following table depicts the various user permission levels in a project. ...@@ -102,7 +103,6 @@ The following table depicts the various user permission levels in a project.
| Push to protected branches | | | | ✓ | ✓ | | Push to protected branches | | | | ✓ | ✓ |
| Turn on/off protected branch push for devs | | | | ✓ | ✓ | | Turn on/off protected branch push for devs | | | | ✓ | ✓ |
| Enable/disable tag protections | | | | ✓ | ✓ | | Enable/disable tag protections | | | | ✓ | ✓ |
| Rewrite/remove Git tags | | | | ✓ | ✓ |
| Edit project | | | | ✓ | ✓ | | Edit project | | | | ✓ | ✓ |
| Add deploy keys to project | | | | ✓ | ✓ | | Add deploy keys to project | | | | ✓ | ✓ |
| Configure project hooks | | | | ✓ | ✓ | | Configure project hooks | | | | ✓ | ✓ |
......
...@@ -85,12 +85,22 @@ on a given project but not both. The current implementation makes use of a `serv ...@@ -85,12 +85,22 @@ on a given project but not both. The current implementation makes use of a `serv
## Using an existing installation of Knative ## Using an existing installation of Knative
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/58941) in GitLab 12.0.
NOTE: **Note:** NOTE: **Note:**
The "invocations" monitoring feature of GitLab serverless will not work when adding an existing installation of Knative. The "invocations" monitoring feature of GitLab serverless will not work when
adding an existing installation of Knative.
It is also possible to use GitLab Serverless with an existing Kubernetes
cluster which already has Knative installed.
Simply:
It is also possible to use GitLab Serverless with an existing Kubernetes cluster which already has Knative installed. 1. Follow the steps to
Simply follow the steps to [add an existing Kubernetes cluster](../index.md#adding-an-existing-kubernetes-cluster) [add an existing Kubernetes cluster](../index.md#adding-an-existing-kubernetes-cluster).
and then follow the steps to deploy [functions](#deploying-functions) or [serverless applications](#deploying-serverless-applications) onto your cluster. 1. Follow the steps to deploy [functions](#deploying-functions)
or [serverless applications](#deploying-serverless-applications) onto your
cluster.
## Deploying functions ## Deploying functions
......
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