Commit 50587541 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 11c12117 0255e321
---
title: Remove orphan service hooks
merge_request: 48263
author:
type: fixed
# frozen_string_literal: true
class RemoveOrphanServiceHooks < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
class WebHook < ActiveRecord::Base
include EachBatch
self.table_name = 'web_hooks'
def self.service_hooks
where(type: 'ServiceHook')
end
end
class Service < ActiveRecord::Base
self.table_name = 'services'
end
def up
WebHook.service_hooks.where.not(service_id: Service.select(:id)).where.not(service_id: nil).each_batch do |relation|
relation.delete_all
end
end
def down
# no-op
end
end
85a642d60e92a880e0a0699f8dcca42aebe2b5363bfcc3010e647734c7cb7dec
\ No newline at end of file
......@@ -9,8 +9,8 @@ type: howto
# Install GitLab on Microsoft Azure
WARNING:
The GitLab image in the Azure Marketplace is deprecated. You can track GitLab's
efforts to [post a new image](https://gitlab.com/gitlab-com/alliances/microsoft/gitlab-tracker/-/issues/2).
This guide is deprecated and pending an update. For the time being, use GitLab's
[image in the Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/gitlabinc1586447921813.gitlabee?tab=Overview).
Azure is Microsoft's business cloud and GitLab is a pre-configured offering on
the Azure Marketplace. Hopefully, you aren't surprised to hear that Microsoft
......
......@@ -5,6 +5,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import { TABLE_TYPE_DEFAULT, TABLE_TYPE_FREE, TABLE_TYPE_TRIAL } from 'ee/billings/constants';
import { s__ } from '~/locale';
import SubscriptionTableRow from './subscription_table_row.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'SubscriptionTable',
......@@ -12,6 +13,7 @@ export default {
SubscriptionTableRow,
GlLoadingIcon,
},
mixins: [glFeatureFlagsMixin()],
props: {
namespaceName: {
type: String,
......@@ -54,7 +56,11 @@ export default {
};
},
renewButton() {
if (this.isFreePlan && !this.plan.trial && !gon.features.saasManualRenewButton) {
if (!this.glFeatures.saasManualRenewButton) {
return null;
}
if (this.isFreePlan) {
return null;
}
......
......@@ -6,10 +6,6 @@ Array [
"href": "http://test.host/plan/upgrade/bronze",
"text": "Upgrade",
},
Object {
"href": "http://test.host/plan/renew",
"text": "Renew",
},
Object {
"href": "https://customers.gitlab.com/subscriptions",
"text": "Manage",
......@@ -23,10 +19,6 @@ Array [
"href": "http://test.host/plan/upgrade/free",
"text": "Upgrade",
},
Object {
"href": "http://test.host/plan/renew",
"text": "Renew",
},
Object {
"href": "https://customers.gitlab.com/subscriptions",
"text": "Manage",
......@@ -36,10 +28,6 @@ Array [
exports[`SubscriptionTable component given a gold plan with state: isFreePlan=false, upgradable=false, isTrialPlan=false has Renew and Manage buttons 1`] = `
Array [
Object {
"href": "http://test.host/plan/renew",
"text": "Renew",
},
Object {
"href": "https://customers.gitlab.com/subscriptions",
"text": "Manage",
......@@ -49,10 +37,6 @@ Array [
exports[`SubscriptionTable component given a trial-gold plan with state: isFreePlan=false, upgradable=false, isTrialPlan=true has Manage button 1`] = `
Array [
Object {
"href": "http://test.host/plan/renew",
"text": "Renew",
},
Object {
"href": "https://customers.gitlab.com/subscriptions",
"text": "Manage",
......
......@@ -20,6 +20,7 @@ describe('SubscriptionTable component', () => {
const findButtonProps = () =>
wrapper.findAll('a').wrappers.map(x => ({ text: x.text(), href: x.attributes('href') }));
const findRenewButton = () => findButtonProps().filter(({ text }) => text === 'Renew');
const factory = (options = {}) => {
store = new Vuex.Store(initialStore());
......@@ -130,26 +131,39 @@ describe('SubscriptionTable component', () => {
},
);
describe('render button', () => {
window.gon = { features: {} };
afterEach(() => {
window.gon.features = {};
});
describe.each`
planName | planCode | isFreePlan | isTrialPlan | featureFlag | expectedBehavior | testDescription
${'free'} | ${null} | ${true} | ${false} | ${true} | ${false} | ${'does not render the renew button for free plan'}
${'gold-trial'} | ${null} | ${false} | ${true} | ${true} | ${false} | ${'does not render the renew button for trial plan'}
${'silver'} | ${'silver'} | ${false} | ${false} | ${true} | ${true} | ${'renders the renew button for paid plans if feature flag is on'}
${'silver'} | ${'silver'} | ${false} | ${false} | ${false} | ${false} | ${'does not render the renew button for paid plans if feature flag is off'}
`(
'given plan with state: isFreePlan=$isFreePlan and feature flag saasManualRenewButton=$featureFlag',
({ planName, planCode, isFreePlan, featureFlag, testDescription, expectedBehavior }) => {
beforeEach(() => {
factory({
propsData: { namespaceName: TEST_NAMESPACE_NAME },
provide: {
glFeatures: {
saasManualRenewButton: featureFlag,
},
},
});
it('renders the renew button when feature flag is on', () => {
gon.features.saasManualRenewButton = true;
factory({ propsData: { namespaceName: TEST_NAMESPACE_NAME } });
expect(findButtonProps()).toStrictEqual([
{ text: 'Upgrade', href: '' },
{ text: 'Renew', href: '' },
]);
});
Object.assign(store.state, {
isLoadingSubscription: false,
isFreePlan,
plan: {
code: planCode,
name: planName,
upgradable: true,
},
});
});
it('does not render the renew button when the feature flag is off', () => {
gon.features.saasManualRenewButton = false;
factory({ propsData: { namespaceName: TEST_NAMESPACE_NAME } });
expect(findButtonProps()).toStrictEqual([{ text: 'Upgrade', href: '' }]);
});
});
it(testDescription, () => {
expect(findRenewButton().length > 0).toBe(expectedBehavior);
});
},
);
});
# frozen_string_literal: true
require 'spec_helper'
require_migration!
require Rails.root.join('db', 'migrate', '20201119125730_add_web_hooks_service_foreign_key.rb')
RSpec.describe RemoveOrphanServiceHooks, schema: 20201203123201 do
let(:web_hooks) { table(:web_hooks) }
let(:services) { table(:services) }
before do
services.create!
web_hooks.create!(service_id: services.first.id, type: 'ServiceHook')
web_hooks.create!(service_id: nil)
AddWebHooksServiceForeignKey.new.down
web_hooks.create!(service_id: non_existing_record_id, type: 'ServiceHook')
AddWebHooksServiceForeignKey.new.up
end
it 'removes service hooks where the referenced service does not exist', :aggregate_failures do
expect { RemoveOrphanServiceHooks.new.up }.to change { web_hooks.count }.by(-1)
expect(web_hooks.where.not(service_id: services.select(:id)).count).to eq(0)
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