chore: Remove template credential experiment's feature flag. (no-changelog) (#14429)

This commit is contained in:
Jaakko Husso
2025-04-07 11:14:14 +03:00
committed by GitHub
parent adbfb44c26
commit 2dfd4205eb
9 changed files with 10 additions and 82 deletions

View File

@@ -56,7 +56,6 @@ describe('Template credentials setup', () => {
it('can be opened from template collection page', () => { it('can be opened from template collection page', () => {
visitTemplateCollectionPage(testData.ecommerceStarterPack); visitTemplateCollectionPage(testData.ecommerceStarterPack);
templateCredentialsSetupPage.enableTemplateCredentialSetupFeatureFlag();
clickUseWorkflowButtonByTitle('Promote new Shopify products'); clickUseWorkflowButtonByTitle('Promote new Shopify products');
templateCredentialsSetupPage.getters templateCredentialsSetupPage.getters

View File

@@ -1,5 +1,4 @@
import { CredentialsModal, MessageBox } from './modals'; import { CredentialsModal, MessageBox } from './modals';
import { overrideFeatureFlag } from '../composables/featureFlags';
import * as formStep from '../composables/setup-template-form-step'; import * as formStep from '../composables/setup-template-form-step';
const credentialsModal = new CredentialsModal(); const credentialsModal = new CredentialsModal();
@@ -12,13 +11,8 @@ export const getters = {
infoCallout: () => cy.getByTestId('info-callout'), infoCallout: () => cy.getByTestId('info-callout'),
}; };
export const enableTemplateCredentialSetupFeatureFlag = () => {
overrideFeatureFlag('017_template_credential_setup_v2', true);
};
export const visitTemplateCredentialSetupPage = (templateId: number) => { export const visitTemplateCredentialSetupPage = (templateId: number) => {
cy.visit(`templates/${templateId}/setup`); cy.visit(`templates/${templateId}/setup`);
enableTemplateCredentialSetupFeatureFlag();
formStep.getFormStep().eq(0).should('be.visible'); formStep.getFormStep().eq(0).should('be.visible');
}; };

View File

@@ -1,9 +1,8 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onBeforeUnmount, watch } from 'vue'; import { computed, onBeforeUnmount, watch } from 'vue';
import { useI18n } from '@/composables/useI18n'; import { useI18n } from '@/composables/useI18n';
import { SETUP_CREDENTIALS_MODAL_KEY, TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT } from '@/constants'; import { SETUP_CREDENTIALS_MODAL_KEY } from '@/constants';
import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { usePostHog } from '@/stores/posthog.store';
import { useUIStore } from '@/stores/ui.store'; import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store'; import { useWorkflowsStore } from '@/stores/workflows.store';
import { doesNodeHaveAllCredentialsFilled } from '@/utils/nodes/nodeTransforms'; import { doesNodeHaveAllCredentialsFilled } from '@/utils/nodes/nodeTransforms';
@@ -11,7 +10,6 @@ import { doesNodeHaveAllCredentialsFilled } from '@/utils/nodes/nodeTransforms';
const workflowsStore = useWorkflowsStore(); const workflowsStore = useWorkflowsStore();
const nodeTypesStore = useNodeTypesStore(); const nodeTypesStore = useNodeTypesStore();
const uiStore = useUIStore(); const uiStore = useUIStore();
const posthogStore = usePostHog();
const i18n = useI18n(); const i18n = useI18n();
const isTemplateSetupCompleted = computed(() => { const isTemplateSetupCompleted = computed(() => {
@@ -32,9 +30,8 @@ const allCredentialsFilled = computed(() => {
}); });
const showButton = computed(() => { const showButton = computed(() => {
const isFeatureEnabled = posthogStore.isFeatureEnabled(TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT);
const isCreatedFromTemplate = !!workflowsStore.workflow?.meta?.templateId; const isCreatedFromTemplate = !!workflowsStore.workflow?.meta?.templateId;
if (!isFeatureEnabled || !isCreatedFromTemplate || isTemplateSetupCompleted.value) { if (!isCreatedFromTemplate || isTemplateSetupCompleted.value) {
return false; return false;
} }

View File

@@ -723,8 +723,6 @@ export const KEEP_AUTH_IN_NDV_FOR_NODES = [
export const MAIN_AUTH_FIELD_NAME = 'authentication'; export const MAIN_AUTH_FIELD_NAME = 'authentication';
export const NODE_RESOURCE_FIELD_NAME = 'resource'; export const NODE_RESOURCE_FIELD_NAME = 'resource';
export const TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT = '017_template_credential_setup_v2';
export const CANVAS_AUTO_ADD_MANUAL_TRIGGER_EXPERIMENT = { export const CANVAS_AUTO_ADD_MANUAL_TRIGGER_EXPERIMENT = {
name: '20_canvas_auto_add_manual_trigger', name: '20_canvas_auto_add_manual_trigger',
control: 'control', control: 'control',
@@ -762,7 +760,6 @@ export const SCHEMA_PREVIEW_EXPERIMENT = {
}; };
export const EXPERIMENTS_TO_TRACK = [ export const EXPERIMENTS_TO_TRACK = [
TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT,
CANVAS_AUTO_ADD_MANUAL_TRIGGER_EXPERIMENT.name, CANVAS_AUTO_ADD_MANUAL_TRIGGER_EXPERIMENT.name,
AI_ASSISTANT_EXPERIMENT.name, AI_ASSISTANT_EXPERIMENT.name,
CREDENTIAL_DOCS_EXPERIMENT.name, CREDENTIAL_DOCS_EXPERIMENT.name,

View File

@@ -9,8 +9,6 @@ import type { ITemplatesWorkflowFull } from '@/Interface';
import { Telemetry } from '@/plugins/telemetry'; import { Telemetry } from '@/plugins/telemetry';
import type { NodeTypesStore } from '@/stores/nodeTypes.store'; import type { NodeTypesStore } from '@/stores/nodeTypes.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import type { PosthogStore } from '@/stores/posthog.store';
import { usePostHog } from '@/stores/posthog.store';
import type { TemplatesStore } from '@/stores/templates.store'; import type { TemplatesStore } from '@/stores/templates.store';
import { useTemplatesStore } from '@/stores/templates.store'; import { useTemplatesStore } from '@/stores/templates.store';
import { useTemplateWorkflow } from '@/utils/templates/templateActions'; import { useTemplateWorkflow } from '@/utils/templates/templateActions';
@@ -53,7 +51,6 @@ describe('templateActions', () => {
resolve: vi.fn(), resolve: vi.fn(),
} as unknown as Router; } as unknown as Router;
let nodeTypesStore: NodeTypesStore; let nodeTypesStore: NodeTypesStore;
let posthogStore: PosthogStore;
let templatesStore: TemplatesStore; let templatesStore: TemplatesStore;
beforeEach(() => { beforeEach(() => {
@@ -66,48 +63,19 @@ describe('templateActions', () => {
vi.spyOn(telemetry, 'track').mockImplementation(() => {}); vi.spyOn(telemetry, 'track').mockImplementation(() => {});
nodeTypesStore = useNodeTypesStore(); nodeTypesStore = useNodeTypesStore();
posthogStore = usePostHog();
templatesStore = useTemplatesStore(); templatesStore = useTemplatesStore();
}); });
describe('When feature flag is disabled', () => { describe('When template has nodes requiring credentials', () => {
const templateId = '1';
beforeEach(async () => {
posthogStore.isFeatureEnabled = vi.fn().mockReturnValue(false);
await useTemplateWorkflow({
externalHooks,
posthogStore,
nodeTypesStore,
telemetry,
templateId,
templatesStore,
router,
source: 'workflow',
});
});
it('should navigate to correct url', async () => {
expect(router.push).toHaveBeenCalledWith({
name: VIEWS.TEMPLATE_IMPORT,
params: { id: templateId },
});
});
});
describe('When feature flag is enabled and template has nodes requiring credentials', () => {
const templateId = testTemplate2.id.toString(); const templateId = testTemplate2.id.toString();
beforeEach(async () => { beforeEach(async () => {
posthogStore.isFeatureEnabled = vi.fn().mockReturnValue(true);
templatesStore.addWorkflows([testTemplate2]); templatesStore.addWorkflows([testTemplate2]);
nodeTypesStore.setNodeTypes([nodeTypeTelegram]); nodeTypesStore.setNodeTypes([nodeTypeTelegram]);
vi.spyOn(nodeTypesStore, 'loadNodeTypesIfNotLoaded').mockResolvedValue(); vi.spyOn(nodeTypesStore, 'loadNodeTypesIfNotLoaded').mockResolvedValue();
await useTemplateWorkflow({ await useTemplateWorkflow({
externalHooks, externalHooks,
posthogStore,
nodeTypesStore, nodeTypesStore,
telemetry, telemetry,
templateId, templateId,
@@ -125,17 +93,15 @@ describe('templateActions', () => {
}); });
}); });
describe("When feature flag is enabled and template doesn't have nodes requiring credentials", () => { describe("When template doesn't have nodes requiring credentials", () => {
const templateId = testTemplate1.id.toString(); const templateId = testTemplate1.id.toString();
beforeEach(async () => { beforeEach(async () => {
posthogStore.isFeatureEnabled = vi.fn().mockReturnValue(true);
templatesStore.addWorkflows([testTemplate1]); templatesStore.addWorkflows([testTemplate1]);
vi.spyOn(nodeTypesStore, 'loadNodeTypesIfNotLoaded').mockResolvedValue(); vi.spyOn(nodeTypesStore, 'loadNodeTypesIfNotLoaded').mockResolvedValue();
await useTemplateWorkflow({ await useTemplateWorkflow({
externalHooks, externalHooks,
posthogStore,
nodeTypesStore, nodeTypesStore,
telemetry, telemetry,
templateId, templateId,

View File

@@ -5,9 +5,8 @@ import type {
IWorkflowTemplate, IWorkflowTemplate,
} from '@/Interface'; } from '@/Interface';
import { getNewWorkflow } from '@/api/workflows'; import { getNewWorkflow } from '@/api/workflows';
import { TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT, VIEWS } from '@/constants'; import { VIEWS } from '@/constants';
import type { useRootStore } from '@/stores/root.store'; import type { useRootStore } from '@/stores/root.store';
import type { PosthogStore } from '@/stores/posthog.store';
import type { useWorkflowsStore } from '@/stores/workflows.store'; import type { useWorkflowsStore } from '@/stores/workflows.store';
import { getNodesWithNormalizedPosition } from '@/utils/nodeViewUtils'; import { getNodesWithNormalizedPosition } from '@/utils/nodeViewUtils';
import type { NodeTypeProvider } from '@/utils/nodeTypes/nodeTypeTransforms'; import type { NodeTypeProvider } from '@/utils/nodeTypes/nodeTypeTransforms';
@@ -147,7 +146,6 @@ async function getFullTemplate(templatesStore: TemplatesStore, templateId: strin
export async function useTemplateWorkflow(opts: { export async function useTemplateWorkflow(opts: {
externalHooks: ExternalHooks; externalHooks: ExternalHooks;
nodeTypesStore: NodeTypesStore; nodeTypesStore: NodeTypesStore;
posthogStore: PosthogStore;
templateId: string; templateId: string;
templatesStore: TemplatesStore; templatesStore: TemplatesStore;
router: Router; router: Router;
@@ -155,13 +153,7 @@ export async function useTemplateWorkflow(opts: {
telemetry: Telemetry; telemetry: Telemetry;
source: string; source: string;
}) { }) {
const { nodeTypesStore, posthogStore, templateId, templatesStore } = opts; const { nodeTypesStore, templateId, templatesStore } = opts;
const openCredentialSetup = posthogStore.isFeatureEnabled(TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT);
if (!openCredentialSetup) {
await openTemplateWorkflowOnNodeView(opts);
return;
}
const [template] = await Promise.all([ const [template] = await Promise.all([
getFullTemplate(templatesStore, templateId), getFullTemplate(templatesStore, templateId),

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onBeforeMount, onMounted, watch } from 'vue'; import { computed, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useSetupTemplateStore } from './setupTemplate.store'; import { useSetupTemplateStore } from './setupTemplate.store';
import N8nHeading from '@n8n/design-system/components/N8nHeading'; import N8nHeading from '@n8n/design-system/components/N8nHeading';
@@ -7,14 +7,12 @@ import N8nLink from '@n8n/design-system/components/N8nLink';
import AppsRequiringCredsNotice from './AppsRequiringCredsNotice.vue'; import AppsRequiringCredsNotice from './AppsRequiringCredsNotice.vue';
import SetupTemplateFormStep from './SetupTemplateFormStep.vue'; import SetupTemplateFormStep from './SetupTemplateFormStep.vue';
import TemplatesView from '../TemplatesView.vue'; import TemplatesView from '../TemplatesView.vue';
import { TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT, VIEWS } from '@/constants'; import { VIEWS } from '@/constants';
import { useI18n } from '@/composables/useI18n'; import { useI18n } from '@/composables/useI18n';
import { usePostHog } from '@/stores/posthog.store';
// Store // Store
const setupTemplateStore = useSetupTemplateStore(); const setupTemplateStore = useSetupTemplateStore();
const i18n = useI18n(); const i18n = useI18n();
const posthogStore = usePostHog();
// Router // Router
const route = useRoute(); const route = useRoute();
@@ -79,15 +77,6 @@ const skipIfTemplateHasNoCreds = async () => {
setupTemplateStore.setTemplateId(templateId.value); setupTemplateStore.setTemplateId(templateId.value);
onBeforeMount(async () => {
if (!posthogStore.isFeatureEnabled(TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT)) {
void router.replace({
name: VIEWS.TEMPLATE_IMPORT,
params: { id: templateId.value },
});
}
});
onMounted(async () => { onMounted(async () => {
await setupTemplateStore.init(); await setupTemplateStore.init();
await skipIfTemplateHasNoCreds(); await skipIfTemplateHasNoCreds();

View File

@@ -6,7 +6,6 @@ import TemplatesView from './TemplatesView.vue';
import type { ITemplatesWorkflow } from '@/Interface'; import type { ITemplatesWorkflow } from '@/Interface';
import { VIEWS } from '@/constants'; import { VIEWS } from '@/constants';
import { useTemplatesStore } from '@/stores/templates.store'; import { useTemplatesStore } from '@/stores/templates.store';
import { usePostHog } from '@/stores/posthog.store';
import { useTemplateWorkflow } from '@/utils/templates/templateActions'; import { useTemplateWorkflow } from '@/utils/templates/templateActions';
import { useExternalHooks } from '@/composables/useExternalHooks'; import { useExternalHooks } from '@/composables/useExternalHooks';
import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { useNodeTypesStore } from '@/stores/nodeTypes.store';
@@ -18,7 +17,6 @@ import { useI18n } from '@/composables/useI18n';
const externalHooks = useExternalHooks(); const externalHooks = useExternalHooks();
const templatesStore = useTemplatesStore(); const templatesStore = useTemplatesStore();
const posthogStore = usePostHog();
const nodeTypesStore = useNodeTypesStore(); const nodeTypesStore = useNodeTypesStore();
const route = useRoute(); const route = useRoute();
@@ -64,7 +62,6 @@ const onOpenTemplate = ({ event, id }: { event: MouseEvent; id: number }) => {
const onUseWorkflow = async ({ event, id }: { event: MouseEvent; id: number }) => { const onUseWorkflow = async ({ event, id }: { event: MouseEvent; id: number }) => {
await useTemplateWorkflow({ await useTemplateWorkflow({
posthogStore,
router, router,
templateId: `${id}`, templateId: `${id}`,
inNewBrowserTab: event.metaKey || event.ctrlKey, inNewBrowserTab: event.metaKey || event.ctrlKey,
@@ -78,8 +75,8 @@ const onUseWorkflow = async ({ event, id }: { event: MouseEvent; id: number }) =
const navigateTo = (e: MouseEvent, page: string, id: string) => { const navigateTo = (e: MouseEvent, page: string, id: string) => {
if (e.metaKey || e.ctrlKey) { if (e.metaKey || e.ctrlKey) {
const route = router.resolve({ name: page, params: { id } }); const { href } = router.resolve({ name: page, params: { id } });
window.open(route.href, '_blank'); window.open(href, '_blank');
return; return;
} else { } else {
void router.push({ name: page, params: { id } }); void router.push({ name: page, params: { id } });

View File

@@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'; import { computed, onMounted, ref, watch } from 'vue';
import { useTemplatesStore } from '@/stores/templates.store'; import { useTemplatesStore } from '@/stores/templates.store';
import { usePostHog } from '@/stores/posthog.store';
import { useTemplateWorkflow } from '@/utils/templates/templateActions'; import { useTemplateWorkflow } from '@/utils/templates/templateActions';
import { useExternalHooks } from '@/composables/useExternalHooks'; import { useExternalHooks } from '@/composables/useExternalHooks';
import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { useNodeTypesStore } from '@/stores/nodeTypes.store';
@@ -13,7 +12,6 @@ import TemplatesView from './TemplatesView.vue';
const externalHooks = useExternalHooks(); const externalHooks = useExternalHooks();
const templatesStore = useTemplatesStore(); const templatesStore = useTemplatesStore();
const posthogStore = usePostHog();
const nodeTypesStore = useNodeTypesStore(); const nodeTypesStore = useNodeTypesStore();
const route = useRoute(); const route = useRoute();
@@ -34,7 +32,6 @@ const template = computed(() => templatesStore.getFullTemplateById(templateId.va
const openTemplateSetup = async (id: string, e: PointerEvent) => { const openTemplateSetup = async (id: string, e: PointerEvent) => {
await useTemplateWorkflow({ await useTemplateWorkflow({
posthogStore,
router, router,
templateId: id, templateId: id,
inNewBrowserTab: e.metaKey || e.ctrlKey, inNewBrowserTab: e.metaKey || e.ctrlKey,