Migrations for Cycle Analytics backend

This change lays the foundation for customizable cycle analytics stages.
The main reason for the change is to extract the event definitions to
separate objects (start_event, end_event) so that it could be easily
customized later on.
This commit is contained in:
Adam Hegyi 2019-08-15 19:19:37 +00:00 committed by Mayra Cabrera
parent 1a20be8682
commit ca6cfde588
10 changed files with 149 additions and 0 deletions

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
module Analytics
module CycleAnalytics
def self.table_name_prefix
'analytics_cycle_analytics_'
end
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
module Analytics
module CycleAnalytics
class ProjectStage < ApplicationRecord
belongs_to :project
end
end
end

View file

@ -283,6 +283,7 @@ class Project < ApplicationRecord
has_one :ci_cd_settings, class_name: 'ProjectCiCdSetting', inverse_of: :project, autosave: true, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :remote_mirrors, inverse_of: :project
has_many :cycle_analytics_stages, class_name: 'Analytics::CycleAnalytics::ProjectStage'
accepts_nested_attributes_for :variables, allow_destroy: true
accepts_nested_attributes_for :project_feature, update_only: true

View file

@ -0,0 +1,5 @@
---
title: Create database tables for the new cycle analytics backend
merge_request: 31621
author:
type: other

View file

@ -0,0 +1,35 @@
# frozen_string_literal: true
class CreateAnalyticsCycleAnalyticsProjectStages < ActiveRecord::Migration[5.2]
DOWNTIME = false
INDEX_PREFIX = 'index_analytics_ca_project_stages_'
def change
create_table :analytics_cycle_analytics_project_stages do |t|
t.timestamps_with_timezone
t.integer :relative_position
t.integer :start_event_identifier, null: false
t.integer :end_event_identifier, null: false
t.references(:project, {
null: false,
foreign_key: { to_table: :projects, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_project_id' }
})
t.references(:start_event_label, {
foreign_key: { to_table: :labels, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_start_event_label_id' }
})
t.references(:end_event_label, {
foreign_key: { to_table: :labels, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_end_event_label_id' }
})
t.boolean :hidden, default: false, null: false
t.boolean :custom, default: true, null: false
t.string :name, null: false, limit: 255
end
add_index :analytics_cycle_analytics_project_stages, [:project_id, :name], unique: true, name: INDEX_PREFIX + 'on_project_id_and_name'
add_index :analytics_cycle_analytics_project_stages, [:relative_position], name: INDEX_PREFIX + 'on_relative_position'
end
end

View file

@ -0,0 +1,35 @@
# frozen_string_literal: true
class CreateAnalyticsCycleAnalyticsGroupStages < ActiveRecord::Migration[5.2]
DOWNTIME = false
INDEX_PREFIX = 'index_analytics_ca_group_stages_'
def change
create_table :analytics_cycle_analytics_group_stages do |t|
t.timestamps_with_timezone
t.integer :relative_position
t.integer :start_event_identifier, null: false
t.integer :end_event_identifier, null: false
t.references(:group, {
null: false,
foreign_key: { to_table: :namespaces, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_group_id' }
})
t.references(:start_event_label, {
foreign_key: { to_table: :labels, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_start_event_label_id' }
})
t.references(:end_event_label, {
foreign_key: { to_table: :labels, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_end_event_label_id' }
})
t.boolean :hidden, default: false, null: false
t.boolean :custom, default: true, null: false
t.string :name, null: false, limit: 255
end
add_index :analytics_cycle_analytics_group_stages, [:group_id, :name], unique: true, name: INDEX_PREFIX + 'on_group_id_and_name'
add_index :analytics_cycle_analytics_group_stages, [:relative_position], name: INDEX_PREFIX + 'on_relative_position'
end
end

View file

@ -26,6 +26,44 @@ ActiveRecord::Schema.define(version: 2019_08_12_070645) do
t.integer "cached_markdown_version"
end
create_table "analytics_cycle_analytics_group_stages", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "relative_position"
t.integer "start_event_identifier", null: false
t.integer "end_event_identifier", null: false
t.bigint "group_id", null: false
t.bigint "start_event_label_id"
t.bigint "end_event_label_id"
t.boolean "hidden", default: false, null: false
t.boolean "custom", default: true, null: false
t.string "name", limit: 255, null: false
t.index ["end_event_label_id"], name: "index_analytics_ca_group_stages_on_end_event_label_id"
t.index ["group_id", "name"], name: "index_analytics_ca_group_stages_on_group_id_and_name", unique: true
t.index ["group_id"], name: "index_analytics_ca_group_stages_on_group_id"
t.index ["relative_position"], name: "index_analytics_ca_group_stages_on_relative_position"
t.index ["start_event_label_id"], name: "index_analytics_ca_group_stages_on_start_event_label_id"
end
create_table "analytics_cycle_analytics_project_stages", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "relative_position"
t.integer "start_event_identifier", null: false
t.integer "end_event_identifier", null: false
t.bigint "project_id", null: false
t.bigint "start_event_label_id"
t.bigint "end_event_label_id"
t.boolean "hidden", default: false, null: false
t.boolean "custom", default: true, null: false
t.string "name", limit: 255, null: false
t.index ["end_event_label_id"], name: "index_analytics_ca_project_stages_on_end_event_label_id"
t.index ["project_id", "name"], name: "index_analytics_ca_project_stages_on_project_id_and_name", unique: true
t.index ["project_id"], name: "index_analytics_ca_project_stages_on_project_id"
t.index ["relative_position"], name: "index_analytics_ca_project_stages_on_relative_position"
t.index ["start_event_label_id"], name: "index_analytics_ca_project_stages_on_start_event_label_id"
end
create_table "appearances", id: :serial, force: :cascade do |t|
t.string "title", null: false
t.text "description", null: false
@ -3632,6 +3670,12 @@ ActiveRecord::Schema.define(version: 2019_08_12_070645) do
t.index ["type"], name: "index_web_hooks_on_type"
end
add_foreign_key "analytics_cycle_analytics_group_stages", "labels", column: "end_event_label_id", on_delete: :cascade
add_foreign_key "analytics_cycle_analytics_group_stages", "labels", column: "start_event_label_id", on_delete: :cascade
add_foreign_key "analytics_cycle_analytics_group_stages", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "analytics_cycle_analytics_project_stages", "labels", column: "end_event_label_id", on_delete: :cascade
add_foreign_key "analytics_cycle_analytics_project_stages", "labels", column: "start_event_label_id", on_delete: :cascade
add_foreign_key "analytics_cycle_analytics_project_stages", "projects", on_delete: :cascade
add_foreign_key "application_settings", "namespaces", column: "custom_project_templates_group_id", on_delete: :nullify
add_foreign_key "application_settings", "projects", column: "file_template_project_id", name: "fk_ec757bd087", on_delete: :nullify
add_foreign_key "application_settings", "projects", column: "instance_administration_project_id", on_delete: :nullify

View file

@ -242,6 +242,7 @@ project:
- cluster_project
- cluster_ingresses
- creator
- cycle_analytics_stages
- group
- namespace
- boards

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
require 'spec_helper'
describe Analytics::CycleAnalytics::ProjectStage do
describe 'associations' do
it { is_expected.to belong_to(:project) }
end
end

View file

@ -98,6 +98,7 @@ describe Project do
it { is_expected.to have_many(:lfs_file_locks) }
it { is_expected.to have_many(:project_deploy_tokens) }
it { is_expected.to have_many(:deploy_tokens).through(:project_deploy_tokens) }
it { is_expected.to have_many(:cycle_analytics_stages) }
it 'has an inverse relationship with merge requests' do
expect(described_class.reflect_on_association(:merge_requests).has_inverse?).to eq(:target_project)