Commit 8de62e6b authored by James Lopez's avatar James Lopez

Merge branch '332450-create-tables' into 'master'

Add upcoming_reconciliations table and model

See merge request gitlab-org/gitlab!63054
parents 0d9ae330 b28478bd
# frozen_string_literal: true
class AddUpcomingReconciliations < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
def up
with_lock_retries do
create_table :upcoming_reconciliations do |t|
t.references :namespace, index: { unique: true }, null: true, foreign_key: { on_delete: :cascade }
t.date :next_reconciliation_date, null: false
t.date :display_alert_from, null: false
t.timestamps_with_timezone
end
end
end
def down
with_lock_retries do
drop_table :upcoming_reconciliations
end
end
end
66e50071130c2bd64be2f52d5c5f348a91883b2e9a9f4241175d1d2ad2a74434
\ No newline at end of file
......@@ -18424,6 +18424,24 @@ CREATE SEQUENCE u2f_registrations_id_seq
ALTER SEQUENCE u2f_registrations_id_seq OWNED BY u2f_registrations.id;
CREATE TABLE upcoming_reconciliations (
id bigint NOT NULL,
namespace_id bigint,
next_reconciliation_date date NOT NULL,
display_alert_from date NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
CREATE SEQUENCE upcoming_reconciliations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE upcoming_reconciliations_id_seq OWNED BY upcoming_reconciliations.id;
CREATE TABLE uploads (
id integer NOT NULL,
size bigint NOT NULL,
......@@ -20291,6 +20309,8 @@ ALTER TABLE ONLY trending_projects ALTER COLUMN id SET DEFAULT nextval('trending
ALTER TABLE ONLY u2f_registrations ALTER COLUMN id SET DEFAULT nextval('u2f_registrations_id_seq'::regclass);
ALTER TABLE ONLY upcoming_reconciliations ALTER COLUMN id SET DEFAULT nextval('upcoming_reconciliations_id_seq'::regclass);
ALTER TABLE ONLY uploads ALTER COLUMN id SET DEFAULT nextval('uploads_id_seq'::regclass);
ALTER TABLE ONLY user_agent_details ALTER COLUMN id SET DEFAULT nextval('user_agent_details_id_seq'::regclass);
......@@ -21939,6 +21959,9 @@ ALTER TABLE ONLY trending_projects
ALTER TABLE ONLY u2f_registrations
ADD CONSTRAINT u2f_registrations_pkey PRIMARY KEY (id);
ALTER TABLE ONLY upcoming_reconciliations
ADD CONSTRAINT upcoming_reconciliations_pkey PRIMARY KEY (id);
ALTER TABLE ONLY uploads
ADD CONSTRAINT uploads_pkey PRIMARY KEY (id);
......@@ -24687,6 +24710,8 @@ CREATE INDEX index_unit_test_failures_failed_at ON ci_unit_test_failures USING b
CREATE UNIQUE INDEX index_unit_test_failures_unique_columns ON ci_unit_test_failures USING btree (unit_test_id, failed_at DESC, build_id);
CREATE UNIQUE INDEX index_upcoming_reconciliations_on_namespace_id ON upcoming_reconciliations USING btree (namespace_id);
CREATE INDEX index_uploads_on_checksum ON uploads USING btree (checksum);
CREATE INDEX index_uploads_on_model_id_and_model_type ON uploads USING btree (model_id, model_type);
......@@ -26538,6 +26563,9 @@ ALTER TABLE ONLY user_custom_attributes
ALTER TABLE ONLY ci_pending_builds
ADD CONSTRAINT fk_rails_480669c3b3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY upcoming_reconciliations
ADD CONSTRAINT fk_rails_497b4938ac FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_pipeline_artifacts
ADD CONSTRAINT fk_rails_4a70390ca6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
......@@ -27,6 +27,7 @@ module EE
has_one :namespace_limit, inverse_of: :namespace
has_one :gitlab_subscription
has_one :elasticsearch_indexed_namespace
has_one :upcoming_reconciliation, inverse_of: :namespace, class_name: "GitlabSubscriptions::UpcomingReconciliation"
has_many :compliance_management_frameworks, class_name: "ComplianceManagement::Framework"
......
# frozen_string_literal: true
module GitlabSubscriptions
class UpcomingReconciliation < ApplicationRecord
belongs_to :namespace, inverse_of: :upcoming_reconciliation, optional: true
validates :namespace, uniqueness: true, presence: { if: proc { ::Gitlab.com? } }
def self.for_self_managed
self.find_by(namespace_id: nil)
end
def display_alert?
next_reconciliation_date >= Date.current && display_alert_from <= Date.current
end
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :upcoming_reconciliation, class: 'GitlabSubscriptions::UpcomingReconciliation' do
next_reconciliation_date { Date.current + 7.days }
display_alert_from { Date.current.beginning_of_day }
trait :self_managed do
namespace { nil }
end
trait :saas do
namespace
end
end
end
......@@ -17,6 +17,7 @@ RSpec.describe Namespace do
it { is_expected.to have_one(:namespace_statistics) }
it { is_expected.to have_one(:namespace_limit) }
it { is_expected.to have_one(:elasticsearch_indexed_namespace) }
it { is_expected.to have_one :upcoming_reconciliation }
it { is_expected.to delegate_method(:shared_runners_seconds).to(:namespace_statistics) }
it { is_expected.to delegate_method(:shared_runners_seconds_last_reset).to(:namespace_statistics) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSubscriptions::UpcomingReconciliation do
describe 'associations' do
it { is_expected.to belong_to(:namespace).optional }
end
describe 'validations' do
# This is needed for the validate_uniqueness_of expectation.
let_it_be(:upcoming_reconciliation) { create(:upcoming_reconciliation, :saas) }
it { is_expected.to validate_uniqueness_of(:namespace) }
it 'does not allow multiple rows with namespace_id nil' do
create(:upcoming_reconciliation, :self_managed)
expect { create(:upcoming_reconciliation, :self_managed) }.to raise_error(
ActiveRecord::RecordInvalid,
'Validation failed: Namespace has already been taken'
)
end
context 'when gitlab.com' do
before do
allow(Gitlab).to receive(:com?).and_return(true)
end
it { is_expected.to validate_presence_of(:namespace) }
end
context 'when not gitlab.com' do
it { is_expected.not_to validate_presence_of(:namespace) }
end
end
describe '#display_alert?' do
let(:upcoming_reconciliation) { build(:upcoming_reconciliation, :saas) }
subject(:display_alert?) { upcoming_reconciliation.display_alert? }
context 'with next_reconciliation_date in future' do
it { is_expected.to eq(true) }
end
context 'with next_reconciliation_date in past' do
before do
upcoming_reconciliation.next_reconciliation_date = Date.yesterday
end
it { is_expected.to eq(false) }
end
context 'with display_alert_from in future' do
before do
upcoming_reconciliation.display_alert_from = 2.days.from_now
end
it { is_expected.to eq(false) }
end
context 'with display_alert_from in past' do
it { is_expected.to eq(true) }
end
end
describe '.for_self_managed' do
it 'returns row where namespace_id is nil' do
upcoming_reconciliation = create(:upcoming_reconciliation, :self_managed)
expect(described_class.for_self_managed).to eq(upcoming_reconciliation)
end
it 'returns nil when there is no row with namespace_id nil' do
expect(described_class.for_self_managed).to eq(nil)
end
end
end
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