From db38aabd1408a938e89d316d71fe1068dfcd98d4 Mon Sep 17 00:00:00 2001 From: Mattermost Build Date: Thu, 17 Jul 2025 13:18:06 +0300 Subject: [PATCH] Purge playbooks data when the plugin gets disabled (#8989) (#9002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Purge playbooks data when the plugin gets disabled * Address copilot comments (cherry picked from commit b925baa21bd4069b8537fb0b856f26b5712090c6) Co-authored-by: Daniel Espino GarcĂ­a --- .../playbooks/actions/local/version.test.ts | 50 +++++++++++++++++++ .../playbooks/actions/local/version.ts | 27 ++++++++++ 2 files changed, 77 insertions(+) diff --git a/app/products/playbooks/actions/local/version.test.ts b/app/products/playbooks/actions/local/version.test.ts index a14337e47..5009b4d8a 100644 --- a/app/products/playbooks/actions/local/version.test.ts +++ b/app/products/playbooks/actions/local/version.test.ts @@ -3,6 +3,7 @@ import {SYSTEM_IDENTIFIERS} from '@constants/database'; import DatabaseManager from '@database/manager'; +import {PLAYBOOK_TABLES} from '@playbooks/constants/database'; import {querySystemValue} from '@queries/servers/system'; import {setPlaybooksVersion} from './version'; @@ -46,4 +47,53 @@ describe('setPlaybooksVersion', () => { expect(error).toBeTruthy(); operator.handleSystem = originalHandleSystem; }); + + it('should purge playbooks when version is empty', async () => { + const database = operator.database; + jest.spyOn(database.adapter, 'unsafeExecute').mockImplementation(() => { + return Promise.resolve(); + }); + + const {data, error} = await setPlaybooksVersion(serverUrl, ''); + expect(error).toBeUndefined(); + expect(data).toBe(true); + + expect(database.adapter.unsafeExecute).toHaveBeenCalledWith({ + sqls: [ + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_RUN}`, []], + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_CHECKLIST}`, []], + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_CHECKLIST_ITEM}`, []], + ], + }); + }); + + it('should not purge playbooks when version is not empty', async () => { + const database = operator.database; + jest.spyOn(database.adapter, 'unsafeExecute').mockImplementation(() => { + return Promise.resolve(); + }); + + const {data, error} = await setPlaybooksVersion(serverUrl, '1.2.3'); + expect(error).toBeUndefined(); + expect(data).toBe(true); + + expect(database.adapter.unsafeExecute).not.toHaveBeenCalled(); + }); + + it('should handle purge playbooks errors', async () => { + const database = operator.database; + jest.spyOn(database.adapter, 'unsafeExecute').mockImplementation(() => { + return Promise.reject(new Error('fail')); + }); + + const {error} = await setPlaybooksVersion(serverUrl, ''); + expect(error).toBeTruthy(); + expect(database.adapter.unsafeExecute).toHaveBeenCalledWith({ + sqls: [ + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_RUN}`, []], + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_CHECKLIST}`, []], + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_CHECKLIST_ITEM}`, []], + ], + }); + }); }); diff --git a/app/products/playbooks/actions/local/version.ts b/app/products/playbooks/actions/local/version.ts index 6b44fcf89..81efe064e 100644 --- a/app/products/playbooks/actions/local/version.ts +++ b/app/products/playbooks/actions/local/version.ts @@ -3,6 +3,7 @@ import {SYSTEM_IDENTIFIERS} from '@constants/database'; import DatabaseManager from '@database/manager'; +import {PLAYBOOK_TABLES} from '@playbooks/constants/database'; export const setPlaybooksVersion = async (serverUrl: string, version: string) => { try { @@ -15,8 +16,34 @@ export const setPlaybooksVersion = async (serverUrl: string, version: string) => prepareRecordsOnly: false, }); + if (version === '') { + const {error} = await purgePlaybooks(serverUrl); + if (error) { + return {error}; + } + } + return {data: true}; } catch (error) { return {error}; } }; + +const purgePlaybooks = async (serverUrl: string) => { + try { + const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl); + await database.write(() => { + return database.adapter.unsafeExecute({ + sqls: [ + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_RUN}`, []], + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_CHECKLIST}`, []], + [`DELETE FROM ${PLAYBOOK_TABLES.PLAYBOOK_CHECKLIST_ITEM}`, []], + ], + }); + }); + } catch (error) { + return {error}; + } + + return {data: true}; +};