提交 607646ef 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 31a432e3
......@@ -192,7 +192,7 @@ db:migrate-from-v12.10.0:
db:rollback:
extends: .db-job-base
script:
- bundle exec rake db:migrate VERSION=20180101160629
- bundle exec rake db:migrate VERSION=20181228175414
- bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
gitlab:setup:
......
......@@ -3,24 +3,35 @@ import {
GlDeprecatedButton,
GlFormGroup,
GlFormInput,
GlLink,
GlModal,
GlModalDirective,
GlSprintf,
} from '@gitlab/ui';
import { escape } from 'lodash';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
import axios from '~/lib/utils/axios_utils';
import { s__, __, sprintf } from '~/locale';
import { s__, __ } from '~/locale';
import createFlash from '~/flash';
export default {
i18n: {
usageSection: s__(
'AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.',
),
setupSection: s__(
"AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.",
),
},
COPY_TO_CLIPBOARD: __('Copy'),
RESET_KEY: __('Reset key'),
components: {
GlDeprecatedButton,
GlFormGroup,
GlFormInput,
GlLink,
GlModal,
GlSprintf,
ClipboardButton,
ToggleButton,
},
......@@ -28,6 +39,14 @@ export default {
'gl-modal': GlModalDirective,
},
props: {
alertsSetupUrl: {
type: String,
required: true,
},
alertsUsageUrl: {
type: String,
required: true,
},
initialAuthorizationKey: {
type: String,
required: false,
......@@ -41,11 +60,6 @@ export default {
type: String,
required: true,
},
learnMoreUrl: {
type: String,
required: false,
default: '',
},
initialActivated: {
type: Boolean,
required: true,
......@@ -59,27 +73,17 @@ export default {
};
},
computed: {
learnMoreDescription() {
return sprintf(
s__(
'AlertService|%{linkStart}Learn more%{linkEnd} about configuring this endpoint to receive alerts.',
),
sections() {
return [
{
linkStart: `<a href="${escape(
this.learnMoreUrl,
)}" target="_blank" rel="noopener noreferrer">`,
linkEnd: '</a>',
text: this.$options.i18n.usageSection,
url: this.alertsUsageUrl,
},
false,
);
},
sectionDescription() {
const desc = s__(
'AlertService|Each alert source must be authorized using the following URL and authorization key.',
);
const learnMoreDesc = this.learnMoreDescription ? ` ${this.learnMoreDescription}` : '';
return `${desc}${learnMoreDesc}`;
{
text: this.$options.i18n.setupSection,
url: this.alertsSetupUrl,
},
];
},
},
watch: {
......@@ -126,7 +130,15 @@ export default {
<template>
<div>
<p v-html="sectionDescription"></p>
<div data-testid="description">
<p v-for="section in sections" :key="section.text">
<gl-sprintf :message="section.text">
<template #link="{ content }">
<gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
</div>
<gl-form-group :label="__('Active')" label-for="activated" label-class="label-bold">
<toggle-button
id="activated"
......
......@@ -7,7 +7,14 @@ export default el => {
return null;
}
const { activated: activatedStr, formPath, authorizationKey, url, learnMoreUrl } = el.dataset;
const {
activated: activatedStr,
alertsSetupUrl,
alertsUsageUrl,
formPath,
authorizationKey,
url,
} = el.dataset;
const activated = parseBoolean(activatedStr);
return new Vue({
......@@ -15,9 +22,10 @@ export default el => {
render(createElement) {
return createElement(AlertsServiceForm, {
props: {
alertsSetupUrl,
alertsUsageUrl,
initialActivated: activated,
formPath,
learnMoreUrl,
initialAuthorizationKey: authorizationKey,
url,
},
......
......@@ -53,7 +53,7 @@ const Api = {
rawFilePath: '/api/:version/projects/:id/repository/files/:path/raw',
issuePath: '/api/:version/projects/:id/issues/:issue_iid',
group(groupId, callback) {
group(groupId, callback = () => {}) {
const url = Api.buildUrl(Api.groupPath).replace(':id', groupId);
return axios.get(url).then(({ data }) => {
callback(data);
......
/* eslint-disable no-underscore-dangle, class-methods-use-this, consistent-return */
/* eslint-disable no-underscore-dangle, class-methods-use-this */
import ListIssue from 'ee_else_ce/boards/models/issue';
import { __ } from '~/locale';
......@@ -8,8 +8,6 @@ import flash from '~/flash';
import boardsStore from '../stores/boards_store';
import ListMilestone from './milestone';
const PER_PAGE = 20;
const TYPES = {
backlog: {
isPreset: true,
......@@ -91,13 +89,7 @@ class List {
}
nextPage() {
if (this.issuesSize > this.issues.length) {
if (this.issues.length / PER_PAGE >= 1) {
this.page += 1;
}
return this.getIssues(false);
}
return boardsStore.goToNextPage(this);
}
getIssues(emptyIssues = true) {
......
/* eslint-disable no-shadow, no-param-reassign */
/* eslint-disable no-shadow, no-param-reassign,consistent-return */
/* global List */
import $ from 'jquery';
......@@ -22,6 +22,7 @@ import ListLabel from '../models/label';
import ListAssignee from '../models/assignee';
import ListMilestone from '../models/milestone';
const PER_PAGE = 20;
const boardsStore = {
disabled: false,
timeTracking: {
......@@ -137,6 +138,17 @@ const boardsStore = {
findIssueLabel(issue, findLabel) {
return issue.labels.find(label => label.id === findLabel.id);
},
goToNextPage(list) {
if (list.issuesSize > list.issues.length) {
if (list.issues.length / PER_PAGE >= 1) {
list.page += 1;
}
return list.getIssues(false);
}
},
addListIssue(list, issue, listFrom, newIndex) {
let moveBeforeId = null;
let moveAfterId = null;
......
<script>
import { escape } from 'lodash';
import helmInstallIllustration from '@gitlab/svgs/dist/illustrations/kubernetes-installation.svg';
import { GlLoadingIcon } from '@gitlab/ui';
import { GlLoadingIcon, GlSprintf, GlLink } from '@gitlab/ui';
import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
import helmLogo from 'images/cluster_app_logos/helm.png';
import jupyterhubLogo from 'images/cluster_app_logos/jupyterhub.png';
......@@ -27,6 +27,8 @@ export default {
applicationRow,
clipboardButton,
GlLoadingIcon,
GlSprintf,
GlLink,
KnativeDomainEditor,
CrossplaneProviderStack,
IngressModsecuritySettings,
......@@ -112,72 +114,6 @@ export default {
certManagerInstalled() {
return this.applications.cert_manager.status === APPLICATION_STATUS.INSTALLED;
},
ingressDescription() {
return sprintf(
escape(
s__(
`ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}.`,
),
),
{
pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb"
target="_blank" rel="noopener noreferrer">
${escape(s__('ClusterIntegration|pricing'))}</a>`,
},
false,
);
},
certManagerDescription() {
return sprintf(
escape(
s__(
`ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates.
Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates
are valid and up-to-date.`,
),
),
{
letsEncrypt: `<a href="https://letsencrypt.org/"
target="_blank" rel="noopener noreferrer">
${escape(s__("ClusterIntegration|Let's Encrypt"))}</a>`,
},
false,
);
},
crossplaneDescription() {
return sprintf(
escape(
s__(
`ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{kubectl} or %{gitlabIntegrationLink}.
Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.`,
),
),
{
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ee/user/clusters/applications.html#crossplane"
target="_blank" rel="noopener noreferrer">
${escape(s__('ClusterIntegration|Gitlab Integration'))}</a>`,
kubectl: `<code>kubectl</code>`,
},
false,
);
},
prometheusDescription() {
return sprintf(
escape(
s__(
`ClusterIntegration|Prometheus is an open-source monitoring system
with %{gitlabIntegrationLink} to monitor deployed applications.`,
),
),
{
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
target="_blank" rel="noopener noreferrer">
${escape(s__('ClusterIntegration|GitLab Integration'))}</a>`,
},
false,
);
},
jupyterInstalled() {
return this.applications.jupyter.status === APPLICATION_STATUS.INSTALLED;
},
......@@ -389,7 +325,21 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
</template>
<template v-else>
<div class="bs-callout bs-callout-info">
<strong v-html="ingressDescription"></strong>
<strong>
<gl-sprintf
:message="
s__(
'ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}.',
)
"
>
<template #pricingLink>
<gl-link href="https://cloud.google.com/compute/pricing#lb" target="_blank">{{
s__('ClusterIntegration|pricing')
}}</gl-link>
</template>
</gl-sprintf>
</strong>
</div>
</template>
</div>
......@@ -414,7 +364,21 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
>
<template #description>
<div>
<p v-html="certManagerDescription"></p>
<p>
<gl-sprintf
:message="
s__(`ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates.
Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates
are valid and up-to-date.`)
"
>
<template #letsEncrypt>
<gl-link href="https://letsencrypt.org/" target="_blank">{{
s__(`ClusterIntegration|Let's Encrypt`)
}}</gl-link>
</template>
</gl-sprintf>
</p>
<div class="form-group">
<label for="cert-manager-issuer-email">
{{ s__('ClusterIntegration|Issuer Email') }}
......@@ -462,7 +426,20 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
title-link="https://prometheus.io/docs/introduction/overview/"
>
<template #description>
<div v-html="prometheusDescription"></div>
<gl-sprintf
:message="
s__(`ClusterIntegration|Prometheus is an open-source monitoring system
with %{gitlabIntegrationLink} to monitor deployed applications.`)
"
>
<template #gitlabIntegrationLink>
<gl-link
href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
target="_blank"
>{{ s__('ClusterIntegration|Gitlab Integration') }}</gl-link
>
</template>
</gl-sprintf>
</template>
</application-row>
<application-row
......@@ -516,7 +493,27 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
>
<template #description>
<div>
<p v-html="crossplaneDescription"></p>
<p>
<gl-sprintf
:message="
s__(
`ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{gitlabIntegrationLink}.
Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.`,
)
"
>
<template #code="{content}">
<code>{{ content }}</code>
</template>
<template #gitlabIntegrationLink>
<gl-link
href="https://docs.gitlab.com/ee/user/clusters/applications.html#crossplane"
target="_blank"
>{{ s__('ClusterIntegration|Gitlab Integration') }}</gl-link
>
</template>
</gl-sprintf>
</p>
<div class="form-group">
<CrossplaneProviderStack :crossplane="crossplane" @set="setCrossplaneProviderStack" />
</div>
......@@ -615,7 +612,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
>
<template #description>
<div>
<p v-if="!rbac" class="rbac-notice bs-callout bs-callout-info gl-mb-0">
<p v-if="!rbac" class="rbac-notice bs-callout bs-callout-info">
{{
s__(`ClusterIntegration|You must have an RBAC-enabled cluster
to install Knative.`)
......@@ -624,7 +621,6 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
{{ __('More information') }}
</a>
</p>
<br />
<p>
{{
s__(`ClusterIntegration|Knative extends Kubernetes to provide
......
......@@ -17,11 +17,14 @@ export default {
},
computed: {
isExpired() {
return this.artifact.expired;
return this.artifact?.expired && !this.isLocked;
},
isLocked() {
return this.artifact?.locked;
},
// Only when the key is `false` we can render this block
willExpire() {
return this.artifact.expired === false;
return this.artifact?.expired === false && !this.isLocked;
},
},
};
......@@ -29,42 +32,45 @@ export default {
<template>
<div class="block">
<div class="title font-weight-bold">{{ s__('Job|Job artifacts') }}</div>
<p
v-if="isExpired || willExpire"
:class="{
'js-artifacts-removed': isExpired,
'js-artifacts-will-be-removed': willExpire,
}"
class="build-detail-row"
data-testid="artifacts-remove-timeline"
>
<span v-if="isExpired">{{ s__('Job|The artifacts were removed') }}</span>
<span v-if="willExpire">{{ s__('Job|The artifacts will be removed') }}</span>
<timeago-tooltip v-if="artifact.expire_at" :time="artifact.expire_at" />
</p>
<p v-else-if="isLocked" class="build-detail-row">
<span data-testid="job-locked-message">{{
s__(
'Job|These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available.',
)
}}</span>
</p>
<div class="btn-group d-flex prepend-top-10" role="group">
<gl-link
v-if="artifact.keep_path"
:href="artifact.keep_path"
class="js-keep-artifacts btn btn-sm btn-default"
class="btn btn-sm btn-default"
data-method="post"
data-testid="keep-artifacts"
>{{ s__('Job|Keep') }}</gl-link
>
<gl-link
v-if="artifact.download_path"
:href="artifact.download_path"
class="js-download-artifacts btn btn-sm btn-default"
class="btn btn-sm btn-default"
download
rel="nofollow"
data-testid="download-artifacts"
>{{ s__('Job|Download') }}</gl-link
>
<gl-link
v-if="artifact.browse_path"
:href="artifact.browse_path"
class="js-browse-artifacts btn btn-sm btn-default"
class="btn btn-sm btn-default"
data-testid="browse-artifacts"
>{{ s__('Job|Browse') }}</gl-link
>
</div>
......
......@@ -7,6 +7,7 @@ import state from './state';
Vue.use(Vuex);
// eslint-disable-next-line import/prefer-default-export
export const createStore = () =>
new Vuex.Store({
state,
......@@ -14,6 +15,3 @@ export const createStore = () =>
actions,
mutations,
});
// Deprecated and to be removed
export default createStore();
......@@ -264,11 +264,12 @@ class GroupsController < Groups::ApplicationController
def export_rate_limit
prefixed_action = "group_#{params[:action]}".to_sym
if Gitlab::ApplicationRateLimiter.throttled?(prefixed_action, scope: [current_user, prefixed_action, @group])
scope = params[:action] == :download_export ? @group : nil
if Gitlab::ApplicationRateLimiter.throttled?(prefixed_action, scope: [current_user, scope].compact)
Gitlab::ApplicationRateLimiter.log_request(request, "#{prefixed_action}_request_limit".to_sym, current_user)
flash[:alert] = _('This endpoint has been requested too many times. Try again later.')
redirect_to edit_group_path(@group)
render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
end
end
......
......@@ -484,7 +484,7 @@ class ProjectsController < Projects::ApplicationController
project_scope = params[:action] == :download_export ? @project : nil
if rate_limiter.throttled?(prefixed_action, scope: [current_user, prefixed_action, project_scope].compact)
if rate_limiter.throttled?(prefixed_action, scope: [current_user, project_scope].compact)
rate_limiter.log_request(request, "#{prefixed_action}_request_limit".to_sym, current_user)
render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
......
......@@ -41,7 +41,7 @@ class AlertsService < Service
end
def description
_('Receive alerts on GitLab from any source')
_('Authorize external services to send alerts to GitLab')
end
def detailed_description
......
.js-alerts-service-settings{ data: { activated: @service.activated?.to_s,
form_path: scoped_integration_path(@service),
authorization_key: @service.token, url: @service.url || _('<namespace / project>'), learn_more_url: 'https://docs.gitlab.com/ee/user/project/integrations/generic_alerts.html' } }
authorization_key: @service.token,
url: @service.url || _('<namespace / project>'),
alerts_setup_url: help_page_path('user/project/integrations/generic_alerts.html', anchor: 'setting-up-generic-alerts'),
alerts_usage_url: help_page_path('user/project/operations/alert_management.html') } }
---
title: Include available instance memory in usage ping
merge_request: 32315
author:
type: other
---
title: Remove nextpage function logic from list model
merge_request: 31904
author: nuwe1
type: other
---
title: Squash database migrations prior to 2019 into one
merge_request: 31936
author:
type: other
---
title: Update artifacts section to show when an artifact is locked
merge_request: 32992
author:
type: changed
---
title: Add more detail to alert integration settings description
merge_request: 33244
author:
type: added
# frozen_string_literal: true
class CreatePrometheusMetrics < ActiveRecord::Migration[4.2]
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
def change
create_table :prometheus_metrics do |t|
t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: false
t.string :title, null: false
t.string :query, null: false
t.string :y_label
t.string :unit
t.string :legend
t.integer :group, null: false, index: true
t.timestamps_with_timezone null: false
end
end
# rubocop:enable Migration/PreventStrings
end
# frozen_string_literal: true
class ChangeProjectIdForPrometheusMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
change_column_null :prometheus_metrics, :project_id, true
end
end
class AddPagesHttpsOnlyToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :projects, :pages_https_only, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
class AddConfidentialNoteEventsToServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column :services, :confidential_note_events, :boolean
change_column_default :services, :confidential_note_events, true
end
def down
remove_column :services, :confidential_note_events
end
end
class AddCommitsCountToMergeRequestDiff < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
MIGRATION = 'AddMergeRequestDiffCommitsCount'.freeze
BATCH_SIZE = 5000
DELAY_INTERVAL = 5.minutes.to_i
class MergeRequestDiff < ActiveRecord::Base
self.table_name = 'merge_request_diffs'
include ::EachBatch
end
disable_ddl_transaction!
def up
add_column :merge_request_diffs, :commits_count, :integer
say 'Populating the MergeRequestDiff `commits_count`'
queue_background_migration_jobs_by_range_at_intervals(MergeRequestDiff, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
end
def down
remove_column :merge_request_diffs, :commits_count
end
end
class ChangeDefaultValueForPagesHttpsOnly < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
change_column_default :projects, :pages_https_only, true
end
def down
change_column_default :projects, :pages_https_only, nil
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class ReworkRedirectRoutesIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
INDEX_NAME_UNIQUE = "index_redirect_routes_on_path_unique_text_pattern_ops"
INDEX_NAME_PERM = "index_redirect_routes_on_path_text_pattern_ops_where_permanent"
INDEX_NAME_TEMP = "index_redirect_routes_on_path_text_pattern_ops_where_temporary"
OLD_INDEX_NAME_PATH_TPOPS = "index_redirect_routes_on_path_text_pattern_ops"
OLD_INDEX_NAME_PATH_LOWER = "index_on_redirect_routes_lower_path"
def up
disable_statement_timeout do
# this is a plain btree on a single boolean column. It'll never be
# selective enough to be valuable.
if index_exists?(:redirect_routes, :permanent)
remove_concurrent_index(:redirect_routes, :permanent)
end
if_not_exists = Gitlab::Database.version.to_f >= 9.5 ? "IF NOT EXISTS" : ""
# Unique index on lower(path) across both types of redirect_routes:
execute("CREATE UNIQUE INDEX CONCURRENTLY #{if_not_exists} #{INDEX_NAME_UNIQUE} ON redirect_routes (lower(path) varchar_pattern_ops);")
# Make two indexes on path -- one for permanent and one for temporary routes:
execute("CREATE INDEX CONCURRENTLY #{if_not_exists} #{INDEX_NAME_PERM} ON redirect_routes (lower(path) varchar_pattern_ops) where (permanent);")
execute("CREATE INDEX CONCURRENTLY #{if_not_exists} #{INDEX_NAME_TEMP} ON redirect_routes (lower(path) varchar_pattern_ops) where (not permanent or permanent is null) ;")
# Remove the old indexes:
# This one needed to be on lower(path) but wasn't so it's replaced with the two above
execute "DROP INDEX CONCURRENTLY IF EXISTS #{OLD_INDEX_NAME_PATH_TPOPS};"
# This one isn't needed because we only ever do = and LIKE on this
# column so the varchar_pattern_ops index is sufficient
execute "DROP INDEX CONCURRENTLY IF EXISTS #{OLD_INDEX_NAME_PATH_LOWER};"
end
end
def down
disable_statement_timeout do
add_concurrent_index(:redirect_routes, :permanent)
execute("CREATE INDEX CONCURRENTLY #{OLD_INDEX_NAME_PATH_TPOPS} ON redirect_routes (path varchar_pattern_ops);")
execute("CREATE INDEX CONCURRENTLY #{OLD_INDEX_NAME_PATH_LOWER} ON redirect_routes (LOWER(path));")
execute("DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME_UNIQUE};")
execute("DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME_PERM};")
execute("DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME_TEMP};")
end
end
end
class AddDefaultProjectCreationSetting < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless column_exists?(:application_settings, :default_project_creation)
add_column_with_default(:application_settings, :default_project_creation, :integer, default: 2) # rubocop:disable Migration/AddColumnWithDefault
end
end
def down
if column_exists?(:application_settings, :default_project_creation)
remove_column(:application_settings, :default_project_creation)
end
end
end
class AddProjectCreationLevelToGroups < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
unless column_exists?(:namespaces, :project_creation_level)
add_column(:namespaces, :project_creation_level, :integer)
end
end
def down
if column_exists?(:namespaces, :project_creation_level)
remove_column(:namespaces, :project_creation_level, :integer)
end
end
end
class AddIndexUpdatedAtToIssues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :issues, :updated_at
end
def down
remove_concurrent_index :issues, :updated_at
end
end
class CreateLfsFileLocks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
create_table :lfs_file_locks do |t|
t.references :project, null: false, foreign_key: { on_delete: :cascade }
t.references :user, null: false, index: true, foreign_key: { on_delete: :cascade }
t.datetime :created_at, null: false # rubocop:disable Migration/Datetime
t.string :path, limit: 511 # rubocop:disable Migration/PreventStrings
end
add_index :lfs_file_locks, [:project_id, :path], unique: true
end
def down
if foreign_keys_for(:lfs_file_locks, :project_id).any?
remove_foreign_key :lfs_file_locks, column: :project_id
end
if index_exists?(:lfs_file_locks, [:project_id, :path])
remove_concurrent_index :lfs_file_locks, [:project_id, :path]
end
drop_table :lfs_file_locks
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddUploaderIndexToUploads < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
remove_concurrent_index :uploads, :path
add_concurrent_index :uploads, [:uploader, :path], using: :btree
end
def down
remove_concurrent_index :uploads, [:uploader, :path]
add_concurrent_index :uploads, :path, using: :btree
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class OptimizeCiJobArtifacts < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
def up
# job_id is just here to be a covering index for index only scans
# since we'll almost always be joining against ci_builds on job_id
add_concurrent_index(:ci_job_artifacts, [:expire_at, :job_id])
add_concurrent_index(:ci_builds, [:artifacts_expire_at], where: "artifacts_file <> ''")
end
def down
remove_concurrent_index(:ci_job_artifacts, [:expire_at, :job_id])
remove_concurrent_index(:ci_builds, [:artifacts_expire_at], where: "artifacts_file <> ''")
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddAutoDevopsDomainToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
def change
add_column :application_settings, :auto_devops_domain, :string
end
# rubocop:enable Migration/PreventStrings
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class CreateUserCallouts < ActiveRecord::Migration[4.2]
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def change
create_table :user_callouts do |t|
t.integer :feature_name, null: false
t.references :user, index: true, foreign_key: { on_delete: :cascade }, null: false
end
add_index :user_callouts, [:user_id, :feature_name], unique: true
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddUploadsBuilderContext < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
def change
add_column :uploads, :mount_point, :string
add_column :uploads, :secret, :string
end
# rubocop:enable Migration/PreventStrings
end
class AddUniqueConstraintToTrendingProjectsProjectId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :trending_projects, :project_id, unique: true, name: 'index_trending_projects_on_project_id_unique'
remove_concurrent_index_by_name :trending_projects, 'index_trending_projects_on_project_id'
rename_index :trending_projects, 'index_trending_projects_on_project_id_unique', 'index_trending_projects_on_project_id'
end
def down
rename_index :trending_projects, 'index_trending_projects_on_project_id', 'index_trending_projects_on_project_id_old'
add_concurrent_index :trending_projects, :project_id
remove_concurrent_index_by_name :trending_projects, 'index_trending_projects_on_project_id_old'
end
end
class AddForeignKeysToTodos < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
class Todo < ActiveRecord::Base
self.table_name = 'todos'
include EachBatch
end
BATCH_SIZE = 1000
DOWNTIME = false
disable_ddl_transaction!
def up
Todo.where('NOT EXISTS ( SELECT true FROM users WHERE id=todos.user_id )').each_batch(of: BATCH_SIZE) do |batch|
batch.delete_all
end
Todo.where('NOT EXISTS ( SELECT true FROM users WHERE id=todos.author_id )').each_batch(of: BATCH_SIZE) do |batch|
batch.delete_all
end
Todo.where('note_id IS NOT NULL AND NOT EXISTS ( SELECT true FROM notes WHERE id=todos.note_id )').each_batch(of: BATCH_SIZE) do |batch|
batch.delete_all
end
add_concurrent_foreign_key :todos, :users, column: :user_id, on_delete: :cascade
add_concurrent_foreign_key :todos, :users, column: :author_id, on_delete: :cascade
add_concurrent_foreign_key :todos, :notes, column: :note_id, on_delete: :cascade
end
def down
remove_foreign_key :todos, column: :user_id
remove_foreign_key :todos, column: :author_id
remove_foreign_key :todos, :notes
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
class Issue < ActiveRecord::Base
self.table_name = 'issues'
include EachBatch
end
def up
Gitlab::BackgroundMigration.steal('CopyColumn')
Gitlab::BackgroundMigration.steal('CleanupConcurrentTypeChange')
if migrate_column_type?
if closed_at_for_type_change_exists?
migrate_remaining_rows
else
# Due to some EE merge problems some environments may not have the
# "closed_at_for_type_change" column. If this is the case we have no
# other option than to migrate the data _right now_.
# rubocop:disable Migration/UpdateLargeTable
change_column_type_concurrently(:issues, :closed_at, :datetime_with_timezone)
cleanup_concurrent_column_type_change(:issues, :closed_at)
end
end
end
def down
# Previous migrations already revert the changes made here.
end
def migrate_remaining_rows
Issue.where('closed_at_for_type_change IS NULL AND closed_at IS NOT NULL').each_batch do |batch|
batch.update_all('closed_at_for_type_change = closed_at')
end
cleanup_concurrent_column_type_change(:issues, :closed_at)
end
def migrate_column_type?
# Some environments may have already executed the previous version of this
# migration, thus we don't need to migrate those environments again.
column_for('issues', 'closed_at').type == :datetime # rubocop:disable Migration/Datetime
end
def closed_at_for_type_change_exists?
columns('issues').any? { |col| col.name == 'closed_at_for_type_change' }
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class ResetEventsPrimaryKeySequence < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
class Event < ActiveRecord::Base
self.table_name = 'events'
end
def up
reset_pk_sequence!(Event.table_name)
end
def down
# No-op
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class SchedulePopulateUntrackedUploadsIfNeeded < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
FOLLOW_UP_MIGRATION = 'PopulateUntrackedUploads'.freeze
class UntrackedFile < ActiveRecord::Base
include EachBatch
self.table_name = 'untracked_files_for_uploads'
end
def up
if table_exists?(:untracked_files_for_uploads)
process_or_remove_table
end
end
def down
# nothing
end
private
def process_or_remove_table
if UntrackedFile.all.empty?
drop_temp_table
else
schedule_populate_untracked_uploads_jobs
end
end
def drop_temp_table
drop_table(:untracked_files_for_uploads, if_exists: true)
end
def schedule_populate_untracked_uploads_jobs
say "Scheduling #{FOLLOW_UP_MIGRATION} background migration jobs since there are rows in untracked_files_for_uploads."
bulk_queue_background_migration_jobs_by_range(
UntrackedFile, FOLLOW_UP_MIGRATION)
end
end
# frozen_string_literal: true
class CreateChatopsTables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
create_table :ci_pipeline_chat_data, id: :bigserial do |t|
t.integer :pipeline_id, null: false
t.references :chat_name, foreign_key: { on_delete: :cascade }, null: false
t.text :response_url, null: false # rubocop:disable Migration/AddLimitToTextColumns
# A pipeline can only contain one row in this table, hence this index is
# unique.
t.index :pipeline_id, unique: true
t.index :chat_name_id
end
# rubocop:disable Migration/AddConcurrentForeignKey
add_foreign_key :ci_pipeline_chat_data, :ci_pipelines,
column: :pipeline_id,
on_delete: :cascade
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddClosedByToIssues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
add_column :issues, :closed_by_id, :integer
add_concurrent_foreign_key :issues, :users, column: :closed_by_id, on_delete: :nullify
end
def down
remove_foreign_key :issues, column: :closed_by_id
remove_column :issues, :closed_by_id
end
end
class AddExternalIpToClustersApplicationsIngress < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
def change
add_column :clusters_applications_ingress, :external_ip, :string
end
# rubocop:enable Migration/PreventStrings
end
class AddPartialIndexToProjectsForIndexOnlyScans < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'index_projects_on_id_partial_for_visibility'
disable_ddl_transaction!
# Adds a partial index to leverage index-only scans when looking up project ids
def up
unless index_exists?(:projects, :id, name: INDEX_NAME)
add_concurrent_index :projects, :id, name: INDEX_NAME, unique: true, where: 'visibility_level IN (10,20)'
end
end
def down
if index_exists?(:projects, :id, name: INDEX_NAME)
remove_concurrent_index_by_name :projects, INDEX_NAME
end
end
end
class CreateBadges < ActiveRecord::Migration[4.2]
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
def change
create_table :badges do |t|
t.string :link_url, null: false
t.string :image_url, null: false
t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: true
t.integer :group_id, index: true, null: true
t.string :type, null: false
t.timestamps_with_timezone null: false
end
# rubocop:disable Migration/AddConcurrentForeignKey
add_foreign_key :badges, :namespaces, column: :group_id, on_delete: :cascade
# rubocop:enable Migration/AddConcurrentForeignKey
end
# rubocop:enable Migration/PreventStrings
end
class CreateClustersApplicationsRunners < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
create_table :clusters_applications_runners do |t|
t.references :cluster, null: false, foreign_key: { on_delete: :cascade }
t.references :runner, references: :ci_runners
t.index :runner_id
t.index :cluster_id, unique: true
t.integer :status, null: false
t.timestamps_with_timezone null: false
t.string :version, null: false # rubocop:disable Migration/PreventStrings
t.text :status_reason # rubocop:disable Migration/AddLimitToTextColumns
end
add_concurrent_foreign_key :clusters_applications_runners, :ci_runners,
column: :runner_id,
on_delete: :nullify
end
def down
if foreign_keys_for(:clusters_applications_runners, :runner_id).any?
remove_foreign_key :clusters_applications_runners, column: :runner_id
end
drop_table :clusters_applications_runners
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class UsersNameLowerIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
INDEX_NAME = 'index_on_users_name_lower'
disable_ddl_transaction!
def up
# On GitLab.com this produces an index with a size of roughly 60 MB.
execute "CREATE INDEX CONCURRENTLY #{INDEX_NAME} ON users (LOWER(name))"
end
def down
execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME}"
end
end
class AddPagesDomainVerification < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
add_column :pages_domains, :verified_at, :datetime_with_timezone
add_column :pages_domains, :verification_code, :string # rubocop:disable Migration/PreventStrings
end
end
class AddPagesDomainVerifiedAtIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :pages_domains, :verified_at
end
def down
remove_concurrent_index :pages_domains, :verified_at
end
end
class AllowDomainVerificationToBeDisabled < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
add_column :application_settings, :pages_domain_verification_enabled, :boolean, default: true, null: false
end
end
class AddPagesDomainEnabledUntil < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
add_column :pages_domains, :enabled_until, :datetime_with_timezone
end
end
class AddPagesDomainEnabledUntilIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :pages_domains, [:project_id, :enabled_until]
add_concurrent_index :pages_domains, [:verified_at, :enabled_until]
end
def down
remove_concurrent_index :pages_domains, [:verified_at, :enabled_until]
remove_concurrent_index :pages_domains, [:project_id, :enabled_until]
end
end
class PagesDomainsVerificationGracePeriod < ActiveRecord::Migration[4.2]
DOWNTIME = false
class PagesDomain < ActiveRecord::Base
include EachBatch
end
# Allow this migration to resume if it fails partway through
disable_ddl_transaction!
def up
now = Time.now
grace = now + 30.days
PagesDomain.each_batch do |relation|
relation.update_all(verified_at: now, enabled_until: grace)
# Sleep 2 minutes between batches to not overload the DB with dead tuples
sleep(2.minutes) unless relation.reorder(:id).last == PagesDomain.reorder(:id).last
end
end
def down
# no-op
end
end
class AddMaximumTimeoutToCiRunners < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :ci_runners, :maximum_timeout, :integer
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddAllowMaintainerToPushToMergeRequests < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column :merge_requests, :allow_maintainer_to_push, :boolean
end
def down
remove_column :merge_requests, :allow_maintainer_to_push
end
end
class AddIpAddressToRunner < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :ci_runners, :ip_address, :string # rubocop:disable Migration/PreventStrings
end
end
class CreateUserInteractedProjectsTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'user_interacted_projects_non_unique_index'
def up
create_table :user_interacted_projects, id: false do |t|
t.references :user, null: false
t.references :project, null: false
end
add_index :user_interacted_projects, [:project_id, :user_id], name: INDEX_NAME
end
def down
drop_table :user_interacted_projects
end
end
class AddAllowLocalRequestsFromHooksAndServicesToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default(:application_settings, :allow_local_requests_from_hooks_and_services, # rubocop:disable Migration/AddColumnWithDefault
:boolean,
default: false,
allow_null: false)
end
def down
remove_column(:application_settings, :allow_local_requests_from_hooks_and_services)
end
end
class AddChecksumToCiJobArtifacts < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
add_column :ci_job_artifacts, :file_sha256, :binary
end
end
class AddGroupIdToBoardsCe < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
DOWNTIME = false
def up
return if group_id_exists?
# rubocop:disable Migration/AddConcurrentForeignKey
add_column :boards, :group_id, :integer
add_foreign_key :boards, :namespaces, column: :group_id, on_delete: :cascade
add_concurrent_index :boards, :group_id
change_column_null :boards, :project_id, true
end
def down
return unless group_id_exists?
# rubocop:disable Migration/RemoveIndex
remove_foreign_key :boards, column: :group_id
remove_index :boards, :group_id if index_exists? :boards, :group_id
remove_column :boards, :group_id
execute "DELETE from boards WHERE project_id IS NULL"
change_column_null :boards, :project_id, false
end
private
def group_id_exists?
column_exists?(:boards, :group_id)
end
end
class AddIncludePrivateContributionsToUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
add_column :users, :include_private_contributions, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
class CreateCiBuildsMetadataTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
create_table :ci_builds_metadata do |t|
t.integer :build_id, null: false
t.integer :project_id, null: false
t.integer :timeout
t.integer :timeout_source, null: false, default: 1
t.foreign_key :ci_builds, column: :build_id, on_delete: :cascade
t.foreign_key :projects, column: :project_id, on_delete: :cascade
t.index :build_id, unique: true
t.index :project_id
end
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class EnsureForeignKeysOnClustersApplications < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
# rubocop:disable Cop/InBatches
def up
existing = Clusters::Cluster
.joins(:application_ingress)
.where('clusters.id = clusters_applications_ingress.cluster_id')
Clusters::Applications::Ingress.where('NOT EXISTS (?)', existing).in_batches do |batch|
batch.delete_all
end
unless foreign_keys_for(:clusters_applications_ingress, :cluster_id).any?
add_concurrent_foreign_key :clusters_applications_ingress, :clusters,
column: :cluster_id,
on_delete: :cascade
end
existing = Clusters::Cluster
.joins(:application_prometheus)
.where('clusters.id = clusters_applications_prometheus.cluster_id')
Clusters::Applications::Ingress.where('NOT EXISTS (?)', existing).in_batches do |batch|
batch.delete_all
end
unless foreign_keys_for(:clusters_applications_prometheus, :cluster_id).any?
add_concurrent_foreign_key :clusters_applications_prometheus, :clusters,
column: :cluster_id,
on_delete: :cascade
end
end
def down
if foreign_keys_for(:clusters_applications_ingress, :cluster_id).any?
remove_foreign_key :clusters_applications_ingress, column: :cluster_id
end
if foreign_keys_for(:clusters_applications_prometheus, :cluster_id).any?
remove_foreign_key :clusters_applications_prometheus, column: :cluster_id
end
end
end
class CreateInternalIdsTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
create_table :internal_ids, id: :bigserial do |t|
t.references :project, null: false, foreign_key: { on_delete: :cascade }
t.integer :usage, null: false
t.integer :last_value, null: false
t.index [:usage, :project_id], unique: true
end
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddPrivilegedToRunner < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default :clusters_applications_runners, :privileged, :boolean, default: true, allow_null: false # rubocop:disable Migration/AddColumnWithDefault
end
def down
remove_column :clusters_applications_runners, :privileged
end
end
# This migration comes from acts_as_taggable_on_engine (originally 6)
#
# It has been modified to handle no-downtime GitLab migrations. Several
# indexes have been removed since they are not needed for GitLab.
class AddMissingIndexesActsAsTaggableOnEngine < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :taggings, :tag_id unless index_exists? :taggings, :tag_id
add_concurrent_index :taggings, [:taggable_id, :taggable_type] unless index_exists? :taggings, [:taggable_id, :taggable_type]
end
def down
remove_concurrent_index :taggings, :tag_id
remove_concurrent_index :taggings, [:taggable_id, :taggable_type]
end
end
class AddSectionNameIdIndexOnCiBuildTraceSections < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
INDEX_NAME = 'index_ci_build_trace_sections_on_section_name_id'
disable_ddl_transaction!
def up
add_concurrent_index :ci_build_trace_sections, :section_name_id, name: INDEX_NAME
end
def down
remove_concurrent_index :ci_build_trace_sections, :section_name_id, name: INDEX_NAME
end
end
class AddUserInternalRegexToApplicationSetting < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
def up
add_column :application_settings, :user_default_internal_regex, :string, null: true
end
# rubocop:enable Migration/PreventStrings
def down
remove_column :application_settings, :user_default_internal_regex
end
end
class RescheduleCommitsCountForMergeRequestDiff < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
MIGRATION = 'AddMergeRequestDiffCommitsCount'.freeze
BATCH_SIZE = 5000
DELAY_INTERVAL = 5.minutes.to_i
class MergeRequestDiff < ActiveRecord::Base
self.table_name = 'merge_request_diffs'
include ::EachBatch
end
disable_ddl_transaction!
def up
say 'Populating the MergeRequestDiff `commits_count` (reschedule)'
execute("SET statement_timeout TO '60s'")
MergeRequestDiff.where(commits_count: nil).each_batch(of: BATCH_SIZE) do |relation, index|
start_id, end_id = relation.pluck('MIN(id), MAX(id)').first
delay = index * DELAY_INTERVAL
BackgroundMigrationWorker.perform_in(delay, MIGRATION, [start_id, end_id])
end
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddPartialIndexesOnTodos < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
INDEX_NAME_PENDING = "index_todos_on_user_id_and_id_pending"
INDEX_NAME_DONE = "index_todos_on_user_id_and_id_done"
def up
unless index_exists?(:todos, [:user_id, :id], name: INDEX_NAME_PENDING)
add_concurrent_index(:todos, [:user_id, :id], where: "state='pending'", name: INDEX_NAME_PENDING)
end
unless index_exists?(:todos, [:user_id, :id], name: INDEX_NAME_DONE)
add_concurrent_index(:todos, [:user_id, :id], where: "state='done'", name: INDEX_NAME_DONE)
end
end
def down
remove_concurrent_index(:todos, [:user_id, :id], where: "state='pending'", name: INDEX_NAME_PENDING)
remove_concurrent_index(:todos, [:user_id, :id], where: "state='done'", name: INDEX_NAME_DONE)
end
end
class AddExternalAuthorizationServiceTimeoutToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
# We can use the regular `add_column` with a default since `application_settings`
# is a small table.
add_column :application_settings,
:external_authorization_service_timeout,
:float,
default: 0.5
end
def down
remove_column :application_settings, :external_authorization_service_timeout
end
end
# frozen_string_literal: true
class AddHeaderAndFooterBannersToAppearancesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
# rubocop:disable Migration/AddLimitToTextColumns
add_column :appearances, :header_message, :text
add_column :appearances, :header_message_html, :text
add_column :appearances, :footer_message, :text
add_column :appearances, :footer_message_html, :text
add_column :appearances, :message_background_color, :text
add_column :appearances, :message_font_color, :text
# rubocop:enable Migration/AddLimitToTextColumns
end
end
class AddExternalAuthMutualTlsFieldsToProjectSettings < ActiveRecord::Migration[4.2]
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
# rubocop:disable Migration/AddLimitToTextColumns
def change
add_column :application_settings,
:external_auth_client_cert, :text
add_column :application_settings,
:encrypted_external_auth_client_key, :text
add_column :application_settings,
:encrypted_external_auth_client_key_iv, :string
add_column :application_settings,
:encrypted_external_auth_client_key_pass, :string
add_column :application_settings,
:encrypted_external_auth_client_key_pass_iv, :string
end
# rubocop:enable Migration/AddLimitToTextColumns
# rubocop:enable Migration/PreventStrings
end
class CreateDeployTokens < ActiveRecord::Migration[4.2]
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
def change
create_table :deploy_tokens do |t|
t.boolean :revoked, default: false
t.boolean :read_repository, null: false, default: false
t.boolean :read_registry, null: false, default: false
t.datetime_with_timezone :expires_at, null: false
t.datetime_with_timezone :created_at, null: false
t.string :name, null: false
t.string :token, index: { unique: true }, null: false
t.index [:token, :expires_at, :id], where: "(revoked IS FALSE)"
end
end
# rubocop:enable Migration/PreventStrings
end
class AddIndexesForUserActivityQueries < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :events, [:author_id, :project_id] unless index_exists?(:events, [:author_id, :project_id])
add_concurrent_index :user_interacted_projects, :user_id unless index_exists?(:user_interacted_projects, :user_id)
end
def down
remove_concurrent_index :events, [:author_id, :project_id] if index_exists?(:events, [:author_id, :project_id])
remove_concurrent_index :user_interacted_projects, :user_id if index_exists?(:user_interacted_projects, :user_id)
end
end
class AddPushToMergeRequestToNotificationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :notification_settings, :push_to_merge_request, :boolean
end
end
class CreateCiBuildTraceChunks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
create_table :ci_build_trace_chunks, id: :bigserial do |t|
t.integer :build_id, null: false
t.integer :chunk_index, null: false
t.integer :data_store, null: false
t.binary :raw_data
t.foreign_key :ci_builds, column: :build_id, on_delete: :cascade
t.index [:build_id, :chunk_index], unique: true
end
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class RemoveIndexFromEventsTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
remove_concurrent_index :events, :author_id
end
def down
add_concurrent_index :events, :author_id
end
end
class AddIssueDueToNotificationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :notification_settings, :issue_due, :boolean
end
end
class CreateProjectCiCdSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless table_exists?(:project_ci_cd_settings)
create_table(:project_ci_cd_settings) do |t|
t.integer(:project_id, null: false)
t.boolean(:group_runners_enabled, default: true, null: false)
end
end
disable_statement_timeout do
# This particular INSERT will take between 10 and 20 seconds.
execute 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects'
# We add the index and foreign key separately so the above INSERT statement
# takes as little time as possible.
add_concurrent_index(:project_ci_cd_settings, :project_id, unique: true)
add_foreign_key_with_retry
end
end
def down
drop_table :project_ci_cd_settings
end
def add_foreign_key_with_retry
# Between the initial INSERT and the addition of the foreign key some
# projects may have been removed, leaving orphaned rows in our new settings
# table.
loop do
remove_orphaned_settings
begin
add_project_id_foreign_key
break
rescue ActiveRecord::InvalidForeignKey
say 'project_ci_cd_settings contains some orphaned rows, retrying...'
end
end
end
def add_project_id_foreign_key
add_concurrent_foreign_key(:project_ci_cd_settings, :projects, column: :project_id)
end
def remove_orphaned_settings
execute <<~SQL
DELETE FROM project_ci_cd_settings
WHERE NOT EXISTS (
SELECT 1
FROM projects
WHERE projects.id = project_ci_cd_settings.project_id
)
SQL
end
end
class CreateProjectDeployTokens < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :project_deploy_tokens do |t|
t.integer :project_id, null: false
t.integer :deploy_token_id, null: false
t.datetime_with_timezone :created_at, null: false
t.foreign_key :deploy_tokens, column: :deploy_token_id, on_delete: :cascade
t.foreign_key :projects, column: :project_id, on_delete: :cascade
t.index [:project_id, :deploy_token_id], unique: true
end
end
end
class RenameUsersRssTokenToFeedToken < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
# rubocop:disable Migration/UpdateLargeTable
rename_column_concurrently :users, :rss_token, :feed_token
end
def down
cleanup_concurrent_column_rename :users, :feed_token, :rss_token
end
end
class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
connection.exec_query(users_query.to_sql).rows.each do |id, username|
create_namespace(id, username)
# When testing locally I've noticed that these internal users are missing
# the notification email, for more details visit the below link:
# https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/18357#note_68327560
set_notification_email(id)
end
end
def down
# no-op
end
private
def users
@users ||= Arel::Table.new(:users)
end
def namespaces
@namespaces ||= Arel::Table.new(:namespaces)
end
def users_query
condition = users[:ghost].eq(true)
if column_exists?(:users, :support_bot)
condition = condition.or(users[:support_bot].eq(true))
end
users.join(namespaces, Arel::Nodes::OuterJoin)
.on(namespaces[:type].eq(nil).and(namespaces[:owner_id].eq(users[:id])))
.where(namespaces[:owner_id].eq(nil))
.where(condition)
.project(users[:id], users[:username])
end
def create_namespace(user_id, username)
path = Uniquify.new.string(username) do |str|
query = "SELECT id FROM namespaces WHERE parent_id IS NULL AND path='#{str}' LIMIT 1"
connection.exec_query(query).present?
end
insert_query = "INSERT INTO namespaces(owner_id, path, name, created_at, updated_at) VALUES(#{user_id}, '#{path}', '#{path}', NOW(), NOW())"
namespace_id = connection.insert(insert_query)
create_route(namespace_id)
end
def create_route(namespace_id)
return unless namespace_id
row = connection.exec_query("SELECT id, path FROM namespaces WHERE id=#{namespace_id}").first
id, path = row.values_at('id', 'path')
execute("INSERT INTO routes(source_id, source_type, path, name, created_at, updated_at) VALUES(#{id}, 'Namespace', '#{path}', '#{path}', NOW(), NOW())")
end
def set_notification_email(user_id)
execute "UPDATE users SET notification_email = email WHERE notification_email IS NULL AND id = #{user_id}"
end
end
class AddFurtherScopeColumnsToInternalIdTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
change_column_null :internal_ids, :project_id, true
add_column :internal_ids, :namespace_id, :integer, null: true
end
def down
change_column_null :internal_ids, :project_id, false
remove_column :internal_ids, :namespace_id
end
end
class AddIndexConstraintsToInternalIdTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :internal_ids, [:usage, :namespace_id], unique: true, where: 'namespace_id IS NOT NULL'
replace_index(:internal_ids, [:usage, :project_id], name: 'index_internal_ids_on_usage_and_project_id') do
add_concurrent_index :internal_ids, [:usage, :project_id], unique: true, where: 'project_id IS NOT NULL'
end
add_concurrent_foreign_key :internal_ids, :namespaces, column: :namespace_id, on_delete: :cascade
end
def down
remove_concurrent_index :internal_ids, [:usage, :namespace_id]
replace_index(:internal_ids, [:usage, :project_id], name: 'index_internal_ids_on_usage_and_project_id') do
add_concurrent_index :internal_ids, [:usage, :project_id], unique: true
end
remove_foreign_key :internal_ids, column: :namespace_id
end
private
def replace_index(table, columns, name:)
temporary_name = "#{name}_old"
if index_exists?(table, columns, name: name)
rename_index table, name, temporary_name
end
yield
remove_concurrent_index_by_name table, temporary_name
end
end
class AddTmpStagePriorityIndexToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index(:ci_builds, [:stage_id, :stage_idx],
where: 'stage_idx IS NOT NULL', name: 'tmp_build_stage_position_index')
end
def down
remove_concurrent_index_by_name(:ci_builds, 'tmp_build_stage_position_index')
end
end
class AddIndexToCiStage < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :ci_stages, :position, :integer
end
end
class AddIndexToCiJobArtifactsFileStore < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :ci_job_artifacts, :file_store
end
def down
# rubocop:disable Migration/RemoveIndex
remove_index :ci_job_artifacts, :file_store if index_exists?(:ci_job_artifacts, :file_store)
end
end
class AddPipelineBuildForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
execute <<~SQL
DELETE FROM ci_builds WHERE project_id IS NULL OR commit_id IS NULL
SQL
execute <<~SQL
DELETE FROM ci_builds WHERE NOT EXISTS
(SELECT true FROM ci_pipelines WHERE ci_pipelines.id = ci_builds.commit_id)
AND stage_id IS NULL
SQL
add_concurrent_foreign_key(:ci_builds, :ci_pipelines, column: :commit_id)
end
def down
return unless foreign_key_exists?(:ci_builds, :ci_pipelines, column: :commit_id)
remove_foreign_key(:ci_builds, column: :commit_id)
end
end
class CleanupBuildStageMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
TMP_INDEX = 'tmp_id_stage_partial_null_index'.freeze
disable_ddl_transaction!
class Build < ActiveRecord::Base
include EachBatch
self.table_name = 'ci_builds'
self.inheritance_column = :_type_disabled
end
def up
disable_statement_timeout do
##
# We steal from the background migrations queue to catch up with the
# scheduled migrations set.
#
Gitlab::BackgroundMigration.steal('MigrateBuildStage')
##
# We add temporary index, to make iteration over batches more performant.
# Conditional here is to avoid the need of doing that in a separate
# migration file to make this operation idempotent.
#
unless index_exists_by_name?(:ci_builds, TMP_INDEX)
add_concurrent_index(:ci_builds, :id, where: 'stage_id IS NULL', name: TMP_INDEX)
end
##
# We check if there are remaining rows that should be migrated (for example
# if Sidekiq / Redis fails / is restarted, what could result in not all
# background migrations being executed correctly.
#
# We migrate remaining rows synchronously in a blocking way, to make sure
# that when this migration is done we are confident that all rows are
# already migrated.
#
Build.where('stage_id IS NULL').each_batch(of: 50) do |batch|
range = batch.pluck('MIN(id)', 'MAX(id)').first
Gitlab::BackgroundMigration::MigrateBuildStage.new.perform(*range)
end
##
# We remove temporary index, because it is not required during standard
# operations and runtime.
#
remove_concurrent_index_by_name(:ci_builds, TMP_INDEX)
end
end
def down
if index_exists_by_name?(:ci_builds, TMP_INDEX)
disable_statement_timeout do
remove_concurrent_index_by_name(:ci_builds, TMP_INDEX)
end
end
end
end
class AddPagesAccessLevelToProjectFeature < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
DOWNTIME = false
# rubocop: disable Migration/UpdateLargeTable
# rubocop: disable Migration/AddColumnWithDefault
def up
add_column_with_default(:project_features, :pages_access_level, :integer, default: ProjectFeature::PUBLIC, allow_null: false)
change_column_default(:project_features, :pages_access_level, ProjectFeature::ENABLED)
end
# rubocop: enable Migration/UpdateLargeTable
# rubocop: enable Migration/AddColumnWithDefault
def down
remove_column :project_features, :pages_access_level
end
end
class AddEnforceTermsToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
# rubocop:disable Migration/SaferBooleanColumn
add_column :application_settings, :enforce_terms, :boolean, default: false
end
end
class CreateApplicationSettingTerms < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
# rubocop:disable Migration/AddLimitToTextColumns
def change
create_table :application_setting_terms do |t|
t.integer :cached_markdown_version
t.text :terms, null: false
t.text :terms_html
end
end
# rubocop:enable Migration/AddLimitToTextColumns
end
class AddPipelineIidToCiPipelines < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
add_column :ci_pipelines, :iid, :integer
end
def down
remove_column :ci_pipelines, :iid, :integer
end
end
class CreateTermAgreements < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
create_table :term_agreements do |t|
t.references :term, index: true, null: false
t.foreign_key :application_setting_terms, column: :term_id
t.references :user, index: true, null: false, foreign_key: { on_delete: :cascade }
t.boolean :accepted, default: false, null: false
t.timestamps_with_timezone null: false
end
add_index :term_agreements, [:user_id, :term_id],
unique: true,
name: 'term_agreements_unique_index'
end
def down
# rubocop:disable Migration/RemoveIndex
remove_index :term_agreements, name: 'term_agreements_unique_index'
drop_table :term_agreements
end
end
class AssureCommitsCountForMergeRequestDiff < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
class MergeRequestDiff < ActiveRecord::Base
self.table_name = 'merge_request_diffs'
include ::EachBatch
end
def up
Gitlab::BackgroundMigration.steal('AddMergeRequestDiffCommitsCount')
MergeRequestDiff.where(commits_count: nil).each_batch(of: 50) do |batch|
range = batch.pluck('MIN(id)', 'MAX(id)').first
Gitlab::BackgroundMigration::AddMergeRequestDiffCommitsCount.new.perform(*range)
end
end
def down
# noop
end
end
class AddIndexConstraintsToPipelineIid < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :ci_pipelines, [:project_id, :iid], unique: true, where: 'iid IS NOT NULL'
end
def down
remove_concurrent_index :ci_pipelines, [:project_id, :iid]
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddAcceptedTermToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
change_table :users do |t|
t.references :accepted_term,
null: true
end
add_concurrent_foreign_key :users, :application_setting_terms, column: :accepted_term_id
end
def down
remove_foreign_key :users, column: :accepted_term_id
remove_column :users, :accepted_term_id
end
end
class AddRunnerTypeToCiRunners < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :ci_runners, :runner_type, :smallint
end
end
class CreateProjectMirrorData < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
# rubocop:disable Migration/PreventStrings
# rubocop:disable Migration/AddLimitToTextColumns
def up
if table_exists?(:project_mirror_data)
add_column :project_mirror_data, :status, :string unless column_exists?(:project_mirror_data, :status)
add_column :project_mirror_data, :jid, :string unless column_exists?(:project_mirror_data, :jid)
add_column :project_mirror_data, :last_error, :text unless column_exists?(:project_mirror_data, :last_error)
else
create_table :project_mirror_data do |t|
t.references :project, index: true, foreign_key: { on_delete: :cascade }
t.string :status
t.string :jid
t.text :last_error
end
end
end
# rubocop:enable Migration/AddLimitToTextColumns
# rubocop:enable Migration/PreventStrings
def down
remove_column :project_mirror_data, :status
remove_column :project_mirror_data, :jid
remove_column :project_mirror_data, :last_error
# ee/db/migrate/20170509153720_create_project_mirror_data_ee.rb will remove the table.
end
end
class CreateRemoteMirrors < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
# rubocop:disable Migration/PreventStrings
def up
return if table_exists?(:remote_mirrors)
create_table :remote_mirrors do |t|
t.references :project, index: true, foreign_key: { on_delete: :cascade }
t.string :url
t.boolean :enabled, default: true
t.string :update_status
t.datetime :last_update_at # rubocop:disable Migration/Datetime
t.datetime :last_successful_update_at # rubocop:disable Migration/Datetime
t.datetime :last_update_started_at # rubocop:disable Migration/Datetime
t.string :last_error
t.boolean :only_protected_branches, default: false, null: false
t.string :remote_name
t.text :encrypted_credentials # rubocop:disable Migration/AddLimitToTextColumns
t.string :encrypted_credentials_iv
t.string :encrypted_credentials_salt
# rubocop:disable Migration/Timestamps
t.timestamps null: false
end
end
# rubocop:enable Migration/PreventStrings
def down
# ee/db/migrate/20160321161032_create_remote_mirrors_ee.rb will remove the table
end
end
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册