Remove serverless functions on version archivation (#9535)
Fixes https://github.com/twentyhq/core-team-issues/issues/52 - contrary to title, we do not remove serverless functions on workflow version archivation because serverless fucntion might be used in another workflow version - we fix the serverless funciton version displayed in the code step - we allow test function version in step display right drawer - we delete serverless function only when serverless function has no published version
This commit is contained in:
@ -591,13 +591,17 @@ describe('should work as expected for the different field types', () => {
|
||||
],
|
||||
},
|
||||
{
|
||||
not: {
|
||||
phones: {
|
||||
primaryPhoneNumber: {
|
||||
ilike: '%1234567890%',
|
||||
and: [
|
||||
{
|
||||
not: {
|
||||
phones: {
|
||||
primaryPhoneNumber: {
|
||||
ilike: '%1234567890%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
and: [
|
||||
|
||||
@ -848,7 +848,7 @@ const computeFilterRecordGqlOperationFilter = (
|
||||
],
|
||||
};
|
||||
case ViewFilterOperand.DoesNotContain:
|
||||
return {
|
||||
return {
|
||||
and: [
|
||||
{
|
||||
not: {
|
||||
|
||||
@ -323,9 +323,7 @@ export const isRecordMatchingFilter = ({
|
||||
case FieldMetadataType.Phones: {
|
||||
const phonesFilter = filterValue as PhonesFilter;
|
||||
|
||||
const keys: (keyof PhonesFilter)[] = [
|
||||
'primaryPhoneNumber'
|
||||
];
|
||||
const keys: (keyof PhonesFilter)[] = ['primaryPhoneNumber'];
|
||||
|
||||
return keys.some((key) => {
|
||||
const value = phonesFilter[key];
|
||||
|
||||
@ -3,10 +3,15 @@ import { useRecoilState } from 'recoil';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/states/serverlessFunctionTestDataFamilyState';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
|
||||
export const useTestServerlessFunction = (
|
||||
serverlessFunctionId: string,
|
||||
callback?: (testResult: object) => void,
|
||||
) => {
|
||||
export const useTestServerlessFunction = ({
|
||||
serverlessFunctionId,
|
||||
serverlessFunctionVersion = 'draft',
|
||||
callback,
|
||||
}: {
|
||||
serverlessFunctionId: string;
|
||||
serverlessFunctionVersion?: string;
|
||||
callback?: (testResult: object) => void;
|
||||
}) => {
|
||||
const { executeOneServerlessFunction } = useExecuteOneServerlessFunction();
|
||||
const [serverlessFunctionTestData, setServerlessFunctionTestData] =
|
||||
useRecoilState(serverlessFunctionTestDataFamilyState(serverlessFunctionId));
|
||||
@ -15,7 +20,7 @@ export const useTestServerlessFunction = (
|
||||
const result = await executeOneServerlessFunction({
|
||||
id: serverlessFunctionId,
|
||||
payload: serverlessFunctionTestData.input,
|
||||
version: 'draft',
|
||||
version: serverlessFunctionVersion,
|
||||
});
|
||||
|
||||
if (isDefined(result?.data?.executeOneServerlessFunction?.data)) {
|
||||
|
||||
@ -36,7 +36,7 @@ describe('useServerlessFunctionUpdateFormState', () => {
|
||||
},
|
||||
);
|
||||
const { result } = renderHook(
|
||||
() => useServerlessFunctionUpdateFormState(serverlessFunctionId),
|
||||
() => useServerlessFunctionUpdateFormState({ serverlessFunctionId }),
|
||||
{
|
||||
wrapper: RecoilRoot,
|
||||
},
|
||||
|
||||
@ -20,9 +20,13 @@ type SetServerlessFunctionFormValues = Dispatch<
|
||||
SetStateAction<ServerlessFunctionFormValues>
|
||||
>;
|
||||
|
||||
export const useServerlessFunctionUpdateFormState = (
|
||||
serverlessFunctionId: string,
|
||||
): {
|
||||
export const useServerlessFunctionUpdateFormState = ({
|
||||
serverlessFunctionId,
|
||||
serverlessFunctionVersion = 'draft',
|
||||
}: {
|
||||
serverlessFunctionId: string;
|
||||
serverlessFunctionVersion?: string;
|
||||
}): {
|
||||
formValues: ServerlessFunctionFormValues;
|
||||
setFormValues: SetServerlessFunctionFormValues;
|
||||
loading: boolean;
|
||||
@ -43,7 +47,7 @@ export const useServerlessFunctionUpdateFormState = (
|
||||
|
||||
const { loading } = useGetOneServerlessFunctionSourceCode({
|
||||
id: serverlessFunctionId,
|
||||
version: 'draft',
|
||||
version: serverlessFunctionVersion,
|
||||
onCompleted: (data: FindOneServerlessFunctionSourceCodeQuery) => {
|
||||
const newState = {
|
||||
code: data?.getServerlessFunctionSourceCode || undefined,
|
||||
|
||||
@ -77,6 +77,8 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
actionOptions,
|
||||
}: WorkflowEditActionFormServerlessFunctionProps) => {
|
||||
const serverlessFunctionId = action.settings.input.serverlessFunctionId;
|
||||
const serverlessFunctionVersion =
|
||||
action.settings.input.serverlessFunctionVersion;
|
||||
const theme = useTheme();
|
||||
const tabListId = `${WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID}_${serverlessFunctionId}`;
|
||||
const { activeTabId, setActiveTabId } = useTabList(tabListId);
|
||||
@ -99,7 +101,10 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
);
|
||||
|
||||
const { formValues, setFormValues, loading } =
|
||||
useServerlessFunctionUpdateFormState(serverlessFunctionId);
|
||||
useServerlessFunctionUpdateFormState({
|
||||
serverlessFunctionId,
|
||||
serverlessFunctionVersion,
|
||||
});
|
||||
|
||||
const updateOutputSchemaFromTestResult = async (testResult: object) => {
|
||||
if (actionOptions.readonly === true) {
|
||||
@ -112,10 +117,11 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
});
|
||||
};
|
||||
|
||||
const { testServerlessFunction } = useTestServerlessFunction(
|
||||
const { testServerlessFunction } = useTestServerlessFunction({
|
||||
serverlessFunctionId,
|
||||
updateOutputSchemaFromTestResult,
|
||||
);
|
||||
serverlessFunctionVersion,
|
||||
callback: updateOutputSchemaFromTestResult,
|
||||
});
|
||||
|
||||
const handleSave = useDebouncedCallback(async () => {
|
||||
await updateOneServerlessFunction({
|
||||
@ -314,7 +320,6 @@ export const WorkflowEditActionFormServerlessFunction = ({
|
||||
<WorkflowEditActionFormServerlessFunctionFields
|
||||
functionInput={serverlessFunctionTestData.input}
|
||||
onInputChange={handleTestInputChange}
|
||||
readonly={actionOptions.readonly}
|
||||
/>
|
||||
<StyledCodeEditorContainer>
|
||||
<InputLabel>Result</InputLabel>
|
||||
|
||||
@ -37,9 +37,10 @@ export const SettingsServerlessFunctionDetail = () => {
|
||||
useUpdateOneServerlessFunction(serverlessFunctionId);
|
||||
const { publishOneServerlessFunction } = usePublishOneServerlessFunction();
|
||||
const { formValues, setFormValues, loading } =
|
||||
useServerlessFunctionUpdateFormState(serverlessFunctionId);
|
||||
const { testServerlessFunction } =
|
||||
useTestServerlessFunction(serverlessFunctionId);
|
||||
useServerlessFunctionUpdateFormState({ serverlessFunctionId });
|
||||
const { testServerlessFunction } = useTestServerlessFunction({
|
||||
serverlessFunctionId,
|
||||
});
|
||||
const { code: latestVersionCode } = useGetOneServerlessFunctionSourceCode({
|
||||
id: serverlessFunctionId,
|
||||
version: 'latest',
|
||||
|
||||
@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { basename, dirname, join } from 'path';
|
||||
|
||||
import deepEqual from 'deep-equal';
|
||||
import { Repository } from 'typeorm';
|
||||
import { IsNull, Not, Repository } from 'typeorm';
|
||||
|
||||
import { FileStorageExceptionCode } from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception';
|
||||
import { ServerlessExecuteResult } from 'src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface';
|
||||
@ -58,6 +58,15 @@ export class ServerlessFunctionService {
|
||||
return this.serverlessFunctionRepository.findBy(where);
|
||||
}
|
||||
|
||||
async hasServerlessFunctionPublishedVersion(serverlessFunctionId: string) {
|
||||
return await this.serverlessFunctionRepository.exists({
|
||||
where: {
|
||||
id: serverlessFunctionId,
|
||||
latestVersion: Not(IsNull()),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getServerlessFunctionSourceCode(
|
||||
workspaceId: string,
|
||||
id: string,
|
||||
|
||||
@ -511,11 +511,16 @@ export class WorkflowVersionStepWorkspaceService {
|
||||
}) {
|
||||
switch (step.type) {
|
||||
case WorkflowActionType.CODE: {
|
||||
await this.serverlessFunctionService.deleteOneServerlessFunction({
|
||||
id: step.settings.input.serverlessFunctionId,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
if (
|
||||
!(await this.serverlessFunctionService.hasServerlessFunctionPublishedVersion(
|
||||
step.settings.input.serverlessFunctionId,
|
||||
))
|
||||
) {
|
||||
await this.serverlessFunctionService.deleteOneServerlessFunction({
|
||||
id: step.settings.input.serverlessFunctionId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user