feat: some mp analytics related to automate actions (#2299)
* fix(fe2): better resiliency for when mp cant be loaded * WIP mixpanel track calls * more resiliency improvements * added all clientside tracking calls * run finished event * minor adjustment * feat(automate): revert automationRunTriggerinAssociation * feat(automate): track manual run triggers * feat(automate): backend track automation run created events * fix(automate): manual trigger type gql schema fix * feat(automate): add source based filter to run trigger tracking * fix(automate): fix trigger mock * various minor adjustments * remove comment --------- Co-authored-by: Gergő Jedlicska <gergo@jedlicska.com>
This commit is contained in:
committed by
GitHub
parent
4c76d5f895
commit
bdf27f6218
@@ -109,6 +109,7 @@ import {
|
||||
useAutomationInputEncryptor,
|
||||
type AutomationInputEncryptor
|
||||
} from '~/lib/automate/composables/automations'
|
||||
import { useMixpanel } from '~/lib/core/composables/mp'
|
||||
|
||||
enum AutomationCreateSteps {
|
||||
SelectFunction,
|
||||
@@ -136,6 +137,8 @@ const props = defineProps<{
|
||||
}>()
|
||||
const open = defineModel<boolean>('open', { required: true })
|
||||
|
||||
const mixpanel = useMixpanel()
|
||||
|
||||
const { handleSubmit: handleDetailsSubmit } = useForm<DetailsFormValues>()
|
||||
|
||||
const stepsOrder = computed(() => [
|
||||
@@ -443,6 +446,16 @@ const onDetailsSubmit = handleDetailsSubmit(async () => {
|
||||
return
|
||||
}
|
||||
|
||||
mixpanel.track('Automation Created', {
|
||||
automationId: aId,
|
||||
name,
|
||||
projectId: project.id,
|
||||
functionName: fn.name,
|
||||
functionId: fn.id,
|
||||
functionReleaseId: fnRelease.id,
|
||||
modelId: model.id
|
||||
})
|
||||
|
||||
// Enable
|
||||
await updateAutomation(
|
||||
{
|
||||
|
||||
@@ -57,6 +57,7 @@ import { useCreateAutomateFunction } from '~/lib/automate/composables/management
|
||||
import { useMutationLoading } from '@vue/apollo-composable'
|
||||
import type { AutomateFunctionCreateDialogDoneStep_AutomateFunctionFragment } from '~~/lib/common/generated/gql/graphql'
|
||||
import { automationFunctionRoute } from '~/lib/common/helpers/route'
|
||||
import { useMixpanel } from '~/lib/core/composables/mp'
|
||||
|
||||
enum FunctionCreateSteps {
|
||||
Authorize,
|
||||
@@ -74,6 +75,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
const open = defineModel<boolean>('open', { required: true })
|
||||
|
||||
const mixpanel = useMixpanel()
|
||||
const logger = useLogger()
|
||||
const mutationLoading = useMutationLoading()
|
||||
const createFunction = useCreateAutomateFunction()
|
||||
@@ -96,6 +98,11 @@ const onDetailsSubmit = handleDetailsSubmit(async (values) => {
|
||||
})
|
||||
|
||||
if (res?.id) {
|
||||
mixpanel.track('Automate Function Created', {
|
||||
functionId: res.id,
|
||||
templateId: selectedTemplate.value.id,
|
||||
name: values.name
|
||||
})
|
||||
createdFunction.value = res
|
||||
step.value++
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ import {
|
||||
useAutomationInputEncryptor,
|
||||
type AutomationInputEncryptor
|
||||
} from '~/lib/automate/composables/automations'
|
||||
import { useMixpanel } from '~/lib/core/composables/mp'
|
||||
|
||||
type AutomationRevisionFunction =
|
||||
ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFunctionFragment
|
||||
@@ -145,6 +146,7 @@ const createNewAutomationRevision = useCreateAutomationRevision()
|
||||
const inputEncryption = useAutomationInputEncryptor({ ensureWhen: open })
|
||||
const { triggerNotification } = useGlobalToast()
|
||||
const logger = useLogger()
|
||||
const mixpanel = useMixpanel()
|
||||
|
||||
const selectedModel = ref<CommonModelSelectorModelFragment>()
|
||||
const selectedRelease = ref<SearchAutomateFunctionReleaseItemFragment>()
|
||||
@@ -215,7 +217,7 @@ const onSave = async () => {
|
||||
})
|
||||
|
||||
// TODO: Apollo cache mutation afterwards
|
||||
await createNewAutomationRevision({
|
||||
const res = await createNewAutomationRevision({
|
||||
projectId: props.projectId,
|
||||
input: {
|
||||
automationId: props.automationId,
|
||||
@@ -237,6 +239,15 @@ const onSave = async () => {
|
||||
}
|
||||
}
|
||||
})
|
||||
if (res?.id) {
|
||||
mixpanel.track('Automation Revision Created', {
|
||||
automationId: props.automationId,
|
||||
projectId: props.projectId,
|
||||
functionId: fId,
|
||||
functionReleaseId: rId,
|
||||
modelId: model.id
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
automationEncrypt?.dispose()
|
||||
loading.value = false
|
||||
|
||||
@@ -44,6 +44,7 @@ import type {
|
||||
ProjectPageAutomationHeader_ProjectFragment
|
||||
} from '~/lib/common/generated/gql/graphql'
|
||||
import { projectRoute } from '~/lib/common/helpers/route'
|
||||
import { useMixpanel } from '~/lib/core/composables/mp'
|
||||
import { useUpdateAutomation } from '~/lib/projects/composables/automationManagement'
|
||||
|
||||
graphql(`
|
||||
@@ -80,6 +81,7 @@ const props = defineProps<{
|
||||
const switchId = useId()
|
||||
const loading = useMutationLoading()
|
||||
const updateAutomation = useUpdateAutomation()
|
||||
const mixpanel = useMixpanel()
|
||||
|
||||
const automationsLink = computed(() => projectRoute(props.project.id, 'automations'))
|
||||
const name = computed({
|
||||
@@ -122,7 +124,7 @@ const enabled = computed({
|
||||
enabled: newVal
|
||||
}
|
||||
}
|
||||
await updateAutomation(args, {
|
||||
const res = await updateAutomation(args, {
|
||||
optimisticResponse: {
|
||||
projectMutations: {
|
||||
automationMutations: {
|
||||
@@ -139,6 +141,14 @@ const enabled = computed({
|
||||
failure: `Failed to ${args.input.enabled ? 'enable' : 'disable'} automation`
|
||||
}
|
||||
})
|
||||
if (res?.id) {
|
||||
mixpanel.track('Automation Enabled/Disabled', {
|
||||
automationId: res.id,
|
||||
automationName: res.name,
|
||||
projectId: props.project.id,
|
||||
enabled: res.enabled
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -24,6 +24,7 @@ import { ArrowPathIcon } from '@heroicons/vue/24/outline'
|
||||
import { usePaginatedQuery } from '~/lib/common/composables/graphql'
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
import type { ProjectPageAutomationRuns_AutomationFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import { useMixpanel } from '~/lib/core/composables/mp'
|
||||
import { useTriggerAutomation } from '~/lib/projects/composables/automationManagement'
|
||||
import { projectAutomationPagePaginatedRunsQuery } from '~/lib/projects/graphql/queries'
|
||||
|
||||
@@ -32,6 +33,7 @@ import { projectAutomationPagePaginatedRunsQuery } from '~/lib/projects/graphql/
|
||||
graphql(`
|
||||
fragment ProjectPageAutomationRuns_Automation on Automation {
|
||||
id
|
||||
name
|
||||
enabled
|
||||
isTestAutomation
|
||||
runs(limit: 10) {
|
||||
@@ -65,8 +67,18 @@ const { identifier, onInfiniteLoad } = usePaginatedQuery({
|
||||
resolveCursorFromVariables: (vars) => vars.cursor
|
||||
})
|
||||
const triggerAutomation = useTriggerAutomation()
|
||||
const mixpanel = useMixpanel()
|
||||
|
||||
const onTrigger = () => {
|
||||
triggerAutomation(props.projectId, props.automation.id)
|
||||
const onTrigger = async () => {
|
||||
const res = await triggerAutomation(props.projectId, props.automation.id)
|
||||
if (res) {
|
||||
mixpanel.track('Automation Run Triggered', {
|
||||
automationId: props.automation.id,
|
||||
automationName: props.automation.name,
|
||||
automationRunId: res,
|
||||
projectId: props.projectId,
|
||||
source: 'manual'
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -56,7 +56,7 @@ const documents = {
|
||||
"\n fragment ProjectPageAutomationFunctions_Automation on Automation {\n id\n currentRevision {\n id\n ...ProjectPageAutomationFunctionSettingsDialog_AutomationRevision\n functions {\n release {\n id\n function {\n id\n ...AutomationsFunctionsCard_AutomateFunction\n releases(limit: 1) {\n items {\n id\n }\n }\n }\n }\n ...ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFunction\n }\n }\n }\n": types.ProjectPageAutomationFunctions_AutomationFragmentDoc,
|
||||
"\n fragment ProjectPageAutomationHeader_Automation on Automation {\n id\n name\n enabled\n isTestAutomation\n currentRevision {\n id\n triggerDefinitions {\n ... on VersionCreatedTriggerDefinition {\n model {\n ...ProjectPageLatestItemsModelItem\n }\n }\n }\n }\n }\n": types.ProjectPageAutomationHeader_AutomationFragmentDoc,
|
||||
"\n fragment ProjectPageAutomationHeader_Project on Project {\n id\n ...ProjectPageModelsCardProject\n }\n": types.ProjectPageAutomationHeader_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageAutomationRuns_Automation on Automation {\n id\n enabled\n isTestAutomation\n runs(limit: 10) {\n items {\n ...AutomationRunDetails\n }\n totalCount\n cursor\n }\n }\n": types.ProjectPageAutomationRuns_AutomationFragmentDoc,
|
||||
"\n fragment ProjectPageAutomationRuns_Automation on Automation {\n id\n name\n enabled\n isTestAutomation\n runs(limit: 10) {\n items {\n ...AutomationRunDetails\n }\n totalCount\n cursor\n }\n }\n": types.ProjectPageAutomationRuns_AutomationFragmentDoc,
|
||||
"\n fragment ProjectPageAutomationsEmptyState_Query on Query {\n automateFunctions(limit: 9, filter: { featuredFunctionsOnly: true }) {\n items {\n ...AutomationsFunctionsCard_AutomateFunction\n ...AutomateAutomationCreateDialog_AutomateFunction\n }\n }\n }\n": types.ProjectPageAutomationsEmptyState_QueryFragmentDoc,
|
||||
"\n fragment ProjectPageAutomationsRow_Automation on Automation {\n id\n name\n enabled\n isTestAutomation\n currentRevision {\n id\n triggerDefinitions {\n ... on VersionCreatedTriggerDefinition {\n model {\n id\n name\n }\n }\n }\n }\n runs(limit: 10) {\n totalCount\n items {\n ...AutomationRunDetails\n }\n cursor\n }\n }\n": types.ProjectPageAutomationsRow_AutomationFragmentDoc,
|
||||
"\n fragment ProjectDiscussionsPageHeader_Project on Project {\n id\n name\n }\n": types.ProjectDiscussionsPageHeader_ProjectFragmentDoc,
|
||||
@@ -429,7 +429,7 @@ export function graphql(source: "\n fragment ProjectPageAutomationHeader_Projec
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment ProjectPageAutomationRuns_Automation on Automation {\n id\n enabled\n isTestAutomation\n runs(limit: 10) {\n items {\n ...AutomationRunDetails\n }\n totalCount\n cursor\n }\n }\n"): (typeof documents)["\n fragment ProjectPageAutomationRuns_Automation on Automation {\n id\n enabled\n isTestAutomation\n runs(limit: 10) {\n items {\n ...AutomationRunDetails\n }\n totalCount\n cursor\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment ProjectPageAutomationRuns_Automation on Automation {\n id\n name\n enabled\n isTestAutomation\n runs(limit: 10) {\n items {\n ...AutomationRunDetails\n }\n totalCount\n cursor\n }\n }\n"): (typeof documents)["\n fragment ProjectPageAutomationRuns_Automation on Automation {\n id\n name\n enabled\n isTestAutomation\n runs(limit: 10) {\n items {\n ...AutomationRunDetails\n }\n totalCount\n cursor\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
@@ -335,7 +335,6 @@ export enum AutomateRunStatus {
|
||||
}
|
||||
|
||||
export enum AutomateRunTriggerType {
|
||||
TestType = 'TEST_TYPE',
|
||||
VersionCreated = 'VERSION_CREATED'
|
||||
}
|
||||
|
||||
@@ -1831,7 +1830,7 @@ export type ProjectAutomationMutations = {
|
||||
* Trigger an automation with a fake "version created" trigger. The "version created" will
|
||||
* just refer to the last version of the model.
|
||||
*/
|
||||
trigger: Scalars['Boolean'];
|
||||
trigger: Scalars['String'];
|
||||
update: Automation;
|
||||
};
|
||||
|
||||
@@ -3595,7 +3594,7 @@ export type ProjectPageAutomationHeader_AutomationFragment = { __typename?: 'Aut
|
||||
|
||||
export type ProjectPageAutomationHeader_ProjectFragment = { __typename?: 'Project', id: string, role?: string | null, visibility: ProjectVisibility };
|
||||
|
||||
export type ProjectPageAutomationRuns_AutomationFragment = { __typename?: 'Automation', id: string, enabled: boolean, isTestAutomation: boolean, runs: { __typename?: 'AutomateRunCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'AutomateRun', id: string, status: AutomateRunStatus, createdAt: string, updatedAt: string, functionRuns: Array<{ __typename?: 'AutomateFunctionRun', statusMessage?: string | null, id: string, status: AutomateRunStatus }>, trigger: { __typename?: 'VersionCreatedTrigger', version?: { __typename?: 'Version', id: string } | null, model?: { __typename?: 'Model', id: string } | null } }> } };
|
||||
export type ProjectPageAutomationRuns_AutomationFragment = { __typename?: 'Automation', id: string, name: string, enabled: boolean, isTestAutomation: boolean, runs: { __typename?: 'AutomateRunCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'AutomateRun', id: string, status: AutomateRunStatus, createdAt: string, updatedAt: string, functionRuns: Array<{ __typename?: 'AutomateFunctionRun', statusMessage?: string | null, id: string, status: AutomateRunStatus }>, trigger: { __typename?: 'VersionCreatedTrigger', version?: { __typename?: 'Version', id: string } | null, model?: { __typename?: 'Model', id: string } | null } }> } };
|
||||
|
||||
export type ProjectPageAutomationsEmptyState_QueryFragment = { __typename?: 'Query', automateFunctions: { __typename?: 'AutomateFunctionCollection', items: Array<{ __typename?: 'AutomateFunction', id: string, name: string, isFeatured: boolean, description: string, logo?: string | null, repo: { __typename?: 'BasicGitRepositoryMetadata', id: string, url: string, owner: string, name: string }, releases: { __typename?: 'AutomateFunctionReleaseCollection', items: Array<{ __typename?: 'AutomateFunctionRelease', id: string, inputSchema?: {} | null }> } }> } };
|
||||
|
||||
@@ -4092,7 +4091,7 @@ export type TriggerAutomationMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type TriggerAutomationMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', automationMutations: { __typename?: 'ProjectAutomationMutations', trigger: boolean } } };
|
||||
export type TriggerAutomationMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', automationMutations: { __typename?: 'ProjectAutomationMutations', trigger: string } } };
|
||||
|
||||
export type CreateTestAutomationMutationVariables = Exact<{
|
||||
projectId: Scalars['ID'];
|
||||
@@ -4718,7 +4717,7 @@ export const CommonModelSelectorModelFragmentDoc = {"kind":"Document","definitio
|
||||
export const ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationFunctionSettingsDialog_AutomationRevision"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomationRevision"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"triggerDefinitions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"VersionCreatedTriggerDefinition"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CommonModelSelectorModel"}}]}}]}}]}}]}}]} as unknown as DocumentNode<ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFragment, unknown>;
|
||||
export const ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFunctionFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomationRevisionFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"parameters"}},{"kind":"Field","name":{"kind":"Name","value":"release"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFunctionFragment, unknown>;
|
||||
export const ProjectPageAutomationFunctions_AutomationFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationFunctions_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"currentRevision"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationFunctionSettingsDialog_AutomationRevision"}},{"kind":"Field","name":{"kind":"Name","value":"functions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"release"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationsFunctionsCard_AutomateFunction"}},{"kind":"Field","name":{"kind":"Name","value":"releases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFunction"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectPageAutomationFunctions_AutomationFragment, unknown>;
|
||||
export const ProjectPageAutomationRuns_AutomationFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationRuns_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"isTestAutomation"}},{"kind":"Field","name":{"kind":"Name","value":"runs"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationRunDetails"}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}}]}}]} as unknown as DocumentNode<ProjectPageAutomationRuns_AutomationFragment, unknown>;
|
||||
export const ProjectPageAutomationRuns_AutomationFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationRuns_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"isTestAutomation"}},{"kind":"Field","name":{"kind":"Name","value":"runs"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationRunDetails"}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}}]}}]} as unknown as DocumentNode<ProjectPageAutomationRuns_AutomationFragment, unknown>;
|
||||
export const ProjectPageAutomationPage_AutomationFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationPage_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationHeader_Automation"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationFunctions_Automation"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationRuns_Automation"}}]}}]} as unknown as DocumentNode<ProjectPageAutomationPage_AutomationFragment, unknown>;
|
||||
export const ProjectPageAutomationHeader_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationHeader_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsCardProject"}}]}}]} as unknown as DocumentNode<ProjectPageAutomationHeader_ProjectFragment, unknown>;
|
||||
export const ProjectPageAutomationPage_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationPage_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationHeader_Project"}}]}}]} as unknown as DocumentNode<ProjectPageAutomationPage_ProjectFragment, unknown>;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { OverridedMixpanel } from 'mixpanel-browser'
|
||||
import { useOnAuthStateChange } from '~/lib/auth/composables/auth'
|
||||
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
|
||||
import { md5 } from '~/lib/common/helpers/encodeDecode'
|
||||
@@ -17,16 +16,10 @@ function getMixpanelServerId(): string {
|
||||
/**
|
||||
* Get Mixpanel instance
|
||||
* Note: Mixpanel is not available during SSR because mixpanel-browser only works in the browser!
|
||||
* If this composable is invoked during SSR it will return undefined!
|
||||
*/
|
||||
export function useMixpanel(): OverridedMixpanel {
|
||||
// we're making TS lie here cause we don't want to constantly check if the return of this
|
||||
// is undefined
|
||||
if (process.server) return undefined as unknown as OverridedMixpanel
|
||||
|
||||
export function useMixpanel() {
|
||||
const nuxt = useNuxtApp()
|
||||
const $mixpanel = nuxt.$mixpanel as () => OverridedMixpanel
|
||||
|
||||
const $mixpanel = nuxt.$mixpanel
|
||||
return $mixpanel()
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ export const useTriggerAutomation = () => {
|
||||
})
|
||||
}
|
||||
|
||||
return !!res?.data?.projectMutations?.automationMutations?.trigger
|
||||
return res?.data?.projectMutations?.automationMutations?.trigger
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,67 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { LogicError } from '@speckle/ui-components'
|
||||
import type { OverridedMixpanel } from 'mixpanel-browser'
|
||||
import type { Merge } from 'type-fest'
|
||||
|
||||
/**
|
||||
* mixpanel-browser only supports being ran on the client-side (hence the name)! So it's only going to be accessible
|
||||
* in client-side execution branches
|
||||
*/
|
||||
|
||||
type LimitedMixpanel = Merge<
|
||||
Pick<
|
||||
OverridedMixpanel,
|
||||
'track' | 'init' | 'reset' | 'register' | 'identify' | 'people' | 'add_group'
|
||||
>,
|
||||
{
|
||||
people: Pick<OverridedMixpanel['people'], 'set' | 'set_once'>
|
||||
}
|
||||
>
|
||||
|
||||
const fakeLimitedMixpanel = (): LimitedMixpanel => ({
|
||||
init: noop as LimitedMixpanel['init'],
|
||||
track: noop,
|
||||
reset: noop,
|
||||
register: noop,
|
||||
identify: noop,
|
||||
people: {
|
||||
set: noop,
|
||||
set_once: noop
|
||||
},
|
||||
add_group: noop
|
||||
})
|
||||
|
||||
export default defineNuxtPlugin(async () => {
|
||||
const {
|
||||
public: { mixpanelApiHost, mixpanelTokenId, logCsrEmitProps }
|
||||
} = useRuntimeConfig()
|
||||
const logger = useLogger()
|
||||
|
||||
const mixpanel = process.client
|
||||
? (await import('mixpanel-browser')).default
|
||||
: undefined
|
||||
if (!mixpanel) {
|
||||
return {
|
||||
provide: {
|
||||
mixpanel: () => {
|
||||
throw new Error('Mixpanel is only available on the client-side!')
|
||||
let mixpanel: LimitedMixpanel | undefined = undefined
|
||||
|
||||
try {
|
||||
mixpanel = process.client ? (await import('mixpanel-browser')).default : undefined
|
||||
if (process.server) {
|
||||
mixpanel = {
|
||||
...fakeLimitedMixpanel(),
|
||||
track: () => {
|
||||
throw new Error('mixpanel is not available on the server-side')
|
||||
},
|
||||
identify: () => {
|
||||
throw new Error('mixpanel is not available on the server-side')
|
||||
},
|
||||
register: () => {
|
||||
throw new Error('mixpanel is not available on the server-side')
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn(e, 'Failed to load mixpanel')
|
||||
}
|
||||
|
||||
if (!mixpanel) {
|
||||
// Implement mocked version
|
||||
mixpanel = fakeLimitedMixpanel()
|
||||
}
|
||||
|
||||
// Init
|
||||
@@ -30,7 +73,10 @@ export default defineNuxtPlugin(async () => {
|
||||
|
||||
return {
|
||||
provide: {
|
||||
mixpanel: () => mixpanel
|
||||
mixpanel: () => {
|
||||
if (!mixpanel) throw new LogicError('Mixpanel unexpectedly not defined')
|
||||
return mixpanel
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -11,7 +11,6 @@ enum AutomateRunStatus {
|
||||
|
||||
enum AutomateRunTriggerType {
|
||||
VERSION_CREATED
|
||||
TEST_TYPE
|
||||
}
|
||||
|
||||
type AutomationRevisionFunction {
|
||||
@@ -296,7 +295,7 @@ type ProjectAutomationMutations {
|
||||
Trigger an automation with a fake "version created" trigger. The "version created" will
|
||||
just refer to the last version of the model.
|
||||
"""
|
||||
trigger(automationId: ID!): Boolean!
|
||||
trigger(automationId: ID!): String!
|
||||
createTestAutomation(input: ProjectTestAutomationCreateInput!): Automation!
|
||||
createTestAutomationRun(automationId: ID!): TestAutomationRun!
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import {
|
||||
AutomationFunctionRunRecord,
|
||||
AutomationRunRecord,
|
||||
AutomationTriggerType,
|
||||
AutomationWithRevision,
|
||||
BaseTriggerManifest
|
||||
BaseTriggerManifest,
|
||||
RunTriggerSource
|
||||
} from '@/modules/automate/helpers/types'
|
||||
import { InsertableAutomationRun } from '@/modules/automate/repositories/automations'
|
||||
import { initializeModuleEventEmitter } from '@/modules/shared/services/moduleEventEmitterSetup'
|
||||
@@ -17,10 +19,12 @@ export type AutomateEventsPayloads = {
|
||||
automation: AutomationWithRevision
|
||||
run: InsertableAutomationRun
|
||||
manifests: BaseTriggerManifest[]
|
||||
source: RunTriggerSource
|
||||
triggerType: AutomationTriggerType
|
||||
}
|
||||
[AutomateRunsEvents.StatusUpdated]: {
|
||||
run: AutomationRunRecord
|
||||
functionRuns: AutomationFunctionRunRecord[]
|
||||
functionRun: AutomationFunctionRunRecord
|
||||
automationId: string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,14 +506,14 @@ export = (FF_AUTOMATE_MODULE_ENABLED
|
||||
})
|
||||
})
|
||||
|
||||
await trigger({
|
||||
const { automationRunId } = await trigger({
|
||||
automationId,
|
||||
userId: ctx.userId!,
|
||||
userResourceAccessRules: ctx.resourceAccessRules,
|
||||
projectId: parent.projectId
|
||||
})
|
||||
|
||||
return true
|
||||
return automationRunId
|
||||
},
|
||||
async createTestAutomation(parent, { input }, ctx) {
|
||||
const create = createTestAutomation({
|
||||
@@ -596,6 +596,7 @@ export = (FF_AUTOMATE_MODULE_ENABLED
|
||||
items: []
|
||||
}
|
||||
}
|
||||
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
TestTriggerType,
|
||||
VersionCreationTriggerType
|
||||
} from '@/modules/automate/helpers/types'
|
||||
import { VersionCreationTriggerType } from '@/modules/automate/helpers/types'
|
||||
import {
|
||||
AutomateFunctionTemplateLanguage,
|
||||
AutomateRunTriggerType
|
||||
@@ -50,11 +47,9 @@ export const functionTemplateRepos = <const>[
|
||||
]
|
||||
|
||||
export const dbToGraphqlTriggerTypeMap = <const>{
|
||||
[VersionCreationTriggerType]: AutomateRunTriggerType.VersionCreated,
|
||||
[TestTriggerType]: AutomateRunTriggerType.TestType
|
||||
[VersionCreationTriggerType]: AutomateRunTriggerType.VersionCreated
|
||||
}
|
||||
|
||||
export const graphqlToDbTriggerTypeMap = <const>{
|
||||
[AutomateRunTriggerType.VersionCreated]: VersionCreationTriggerType,
|
||||
[AutomateRunTriggerType.TestType]: TestTriggerType
|
||||
[AutomateRunTriggerType.VersionCreated]: VersionCreationTriggerType
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export type AutomationRunStatus =
|
||||
| 'timeout'
|
||||
| 'canceled'
|
||||
|
||||
export const AutomationRunStatuses: Record<AutomationRunStatus, AutomationRunStatus> = {
|
||||
export const AutomationRunStatuses: { [key in AutomationRunStatus]: key } = {
|
||||
pending: 'pending',
|
||||
initializing: 'initializing',
|
||||
running: 'running',
|
||||
@@ -73,11 +73,13 @@ export type AutomateRevisionFunctionRecord = {
|
||||
automationRevisionId: string
|
||||
}
|
||||
|
||||
export enum RunTriggerSource {
|
||||
Automatic = 'automatic',
|
||||
Manual = 'manual'
|
||||
}
|
||||
|
||||
export const VersionCreationTriggerType = <const>'versionCreation'
|
||||
export const TestTriggerType = <const>'testtttt'
|
||||
export type AutomationTriggerType =
|
||||
| typeof VersionCreationTriggerType
|
||||
| typeof TestTriggerType
|
||||
export type AutomationTriggerType = typeof VersionCreationTriggerType
|
||||
|
||||
export type AutomationTriggerRecordBase<
|
||||
T extends AutomationTriggerType = AutomationTriggerType
|
||||
|
||||
@@ -8,9 +8,10 @@ import {
|
||||
import { Environment } from '@speckle/shared'
|
||||
import {
|
||||
getActiveTriggerDefinitions,
|
||||
getAutomationRunFullTriggers,
|
||||
getFullAutomationRevisionMetadata,
|
||||
getAutomation,
|
||||
getAutomationRevision,
|
||||
getAutomationRunFullTriggers
|
||||
getAutomationRevision
|
||||
} from '@/modules/automate/repositories/automations'
|
||||
import { ScopeRecord } from '@/modules/auth/helpers/types'
|
||||
import { Scopes } from '@speckle/shared'
|
||||
@@ -26,6 +27,7 @@ import {
|
||||
setupAutomationUpdateSubscriptions,
|
||||
setupStatusUpdateSubscriptions
|
||||
} from '@/modules/automate/services/subscriptions'
|
||||
import { setupRunFinishedTracking } from '@/modules/automate/services/tracking'
|
||||
import authGithubAppRest from '@/modules/automate/rest/authGithubApp'
|
||||
|
||||
const { FF_AUTOMATE_MODULE_ENABLED } = Environment.getFeatureFlags()
|
||||
@@ -67,6 +69,9 @@ const initializeEventListeners = () => {
|
||||
getAutomationRunFullTriggers
|
||||
})
|
||||
const setupAutomationUpdateSubscriptionsInvoke = setupAutomationUpdateSubscriptions()
|
||||
const setupRunFinishedTrackingInvoke = setupRunFinishedTracking({
|
||||
getFullAutomationRevisionMetadata
|
||||
})
|
||||
|
||||
const quitters = [
|
||||
VersionsEmitter.listen(
|
||||
@@ -81,7 +86,8 @@ const initializeEventListeners = () => {
|
||||
}
|
||||
),
|
||||
setupStatusUpdateSubscriptionsInvoke(),
|
||||
setupAutomationUpdateSubscriptionsInvoke()
|
||||
setupAutomationUpdateSubscriptionsInvoke(),
|
||||
setupRunFinishedTrackingInvoke()
|
||||
]
|
||||
|
||||
return () => {
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
JsonSchemaInputValidationError
|
||||
} from '@/modules/automate/errors/management'
|
||||
import {
|
||||
AutomationRunStatus,
|
||||
AutomationRunStatuses,
|
||||
VersionCreationTriggerType
|
||||
} from '@/modules/automate/helpers/types'
|
||||
@@ -561,7 +562,7 @@ export const getAutomationsStatus =
|
||||
(a) => a.status === AutomationRunStatuses.pending
|
||||
)
|
||||
|
||||
let status = AutomationRunStatuses.succeeded
|
||||
let status: AutomationRunStatus = AutomationRunStatuses.succeeded
|
||||
let statusMessage = 'All automations have succeeded'
|
||||
|
||||
if (failedAutomations.length) {
|
||||
|
||||
@@ -16,14 +16,14 @@ import {
|
||||
import { Automate } from '@speckle/shared'
|
||||
|
||||
const AutomationRunStatusOrder: { [key in AutomationRunStatus]: number } = {
|
||||
pending: 0,
|
||||
initializing: 1,
|
||||
running: 2,
|
||||
succeeded: 3,
|
||||
failed: 3,
|
||||
canceled: 4,
|
||||
exception: 5,
|
||||
timeout: 5
|
||||
[AutomationRunStatuses.pending]: 0,
|
||||
[AutomationRunStatuses.initializing]: 1,
|
||||
[AutomationRunStatuses.running]: 2,
|
||||
[AutomationRunStatuses.succeeded]: 3,
|
||||
[AutomationRunStatuses.failed]: 3,
|
||||
[AutomationRunStatuses.exception]: 5,
|
||||
[AutomationRunStatuses.timeout]: 5,
|
||||
[AutomationRunStatuses.canceled]: 4
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +148,7 @@ export const reportFunctionRunStatus =
|
||||
|
||||
await AutomateRunsEmitter.emit(AutomateRunsEmitter.events.StatusUpdated, {
|
||||
run: updatedRun,
|
||||
functionRuns: [nextFunctionRunRecord],
|
||||
functionRun: nextFunctionRunRecord,
|
||||
automationId
|
||||
})
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ export const setupStatusUpdateSubscriptions =
|
||||
|
||||
AutomateRunsEmitter.listen(
|
||||
AutomateRunsEmitter.events.StatusUpdated,
|
||||
async ({ run, functionRuns, automationId }) => {
|
||||
async ({ run, functionRun, automationId }) => {
|
||||
const triggers = await getAutomationRunFullTriggers({
|
||||
automationRunId: run.id
|
||||
})
|
||||
@@ -141,7 +141,7 @@ export const setupStatusUpdateSubscriptions =
|
||||
versionId: trigger.version.id,
|
||||
run: {
|
||||
...run,
|
||||
functionRuns,
|
||||
functionRuns: [functionRun],
|
||||
automationId,
|
||||
triggers: undefined
|
||||
},
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import { automateLogger } from '@/logging/logging'
|
||||
import { AutomateRunsEmitter } from '@/modules/automate/events/runs'
|
||||
import {
|
||||
AutomationFunctionRunRecord,
|
||||
AutomationRunRecord,
|
||||
AutomationRunStatus,
|
||||
AutomationRunStatuses,
|
||||
AutomationWithRevision,
|
||||
RunTriggerSource
|
||||
} from '@/modules/automate/helpers/types'
|
||||
import {
|
||||
InsertableAutomationRun,
|
||||
getFullAutomationRevisionMetadata
|
||||
} from '@/modules/automate/repositories/automations'
|
||||
import { mixpanel } from '@/modules/shared/utils/mixpanel'
|
||||
import { throwUncoveredError } from '@speckle/shared'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const isFinished = (runStatus: AutomationRunStatus) => {
|
||||
const finishedStatuses: AutomationRunStatus[] = [
|
||||
AutomationRunStatuses.succeeded,
|
||||
AutomationRunStatuses.failed,
|
||||
AutomationRunStatuses.exception,
|
||||
AutomationRunStatuses.timeout,
|
||||
AutomationRunStatuses.canceled
|
||||
]
|
||||
|
||||
return finishedStatuses.includes(runStatus)
|
||||
}
|
||||
|
||||
export type SetupRunFinishedTrackingDeps = {
|
||||
getFullAutomationRevisionMetadata: typeof getFullAutomationRevisionMetadata
|
||||
}
|
||||
|
||||
const onAutomationRunStatusUpdated =
|
||||
({ getFullAutomationRevisionMetadata }: SetupRunFinishedTrackingDeps) =>
|
||||
async ({
|
||||
run,
|
||||
functionRun,
|
||||
automationId
|
||||
}: {
|
||||
run: AutomationRunRecord
|
||||
functionRun: AutomationFunctionRunRecord
|
||||
automationId: string
|
||||
}) => {
|
||||
if (!isFinished(run.status)) return
|
||||
|
||||
const automationWithRevision = await getFullAutomationRevisionMetadata(
|
||||
run.automationRevisionId
|
||||
)
|
||||
if (!automationWithRevision) {
|
||||
automateLogger.error(
|
||||
{
|
||||
run
|
||||
},
|
||||
'Run revision not found unexpectedly'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const mp = mixpanel({ userEmail: undefined })
|
||||
await mp.track('Automate Function Run Finished', {
|
||||
automationId,
|
||||
automationRevisionId: automationWithRevision.id,
|
||||
automationName: automationWithRevision.name,
|
||||
runId: run.id,
|
||||
functionRunId: functionRun.id,
|
||||
status: functionRun.status,
|
||||
durationInSeconds: dayjs(functionRun.updatedAt).diff(
|
||||
functionRun.createdAt,
|
||||
'second'
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const onRunCreated = async ({
|
||||
automation,
|
||||
run: automationRun,
|
||||
source
|
||||
}: {
|
||||
automation: AutomationWithRevision
|
||||
run: InsertableAutomationRun
|
||||
source: RunTriggerSource
|
||||
}) => {
|
||||
// all triggers, that are automatic result of an action are in a need to be tracked
|
||||
switch (source) {
|
||||
case RunTriggerSource.Automatic: {
|
||||
const mp = mixpanel({ userEmail: undefined })
|
||||
await mp.track('Automation Run Triggered', {
|
||||
automationId: automation.id,
|
||||
automationName: automation.name,
|
||||
automationRunId: automationRun.id,
|
||||
projectId: automation.projectId,
|
||||
source
|
||||
})
|
||||
break
|
||||
}
|
||||
// runs created from a user interaction are tracked in the frontend
|
||||
case RunTriggerSource.Manual:
|
||||
return
|
||||
default:
|
||||
throwUncoveredError(source)
|
||||
}
|
||||
}
|
||||
|
||||
export const setupRunFinishedTracking = (deps: SetupRunFinishedTrackingDeps) => () => {
|
||||
const quitters = [
|
||||
AutomateRunsEmitter.listen(
|
||||
AutomateRunsEmitter.events.StatusUpdated,
|
||||
onAutomationRunStatusUpdated(deps)
|
||||
),
|
||||
AutomateRunsEmitter.listen(AutomateRunsEmitter.events.Created, onRunCreated)
|
||||
]
|
||||
|
||||
return () => quitters.forEach((quitter) => quitter())
|
||||
}
|
||||
@@ -17,7 +17,8 @@ import {
|
||||
VersionCreationTriggerType,
|
||||
BaseTriggerManifest,
|
||||
isVersionCreatedTriggerManifest,
|
||||
LiveAutomation
|
||||
LiveAutomation,
|
||||
RunTriggerSource
|
||||
} from '@/modules/automate/helpers/types'
|
||||
import { getBranchLatestCommits } from '@/modules/core/repositories/branches'
|
||||
import { getCommit } from '@/modules/core/repositories/commits'
|
||||
@@ -219,9 +220,10 @@ export const triggerAutomationRevisionRun =
|
||||
async <M extends BaseTriggerManifest = BaseTriggerManifest>(params: {
|
||||
revisionId: string
|
||||
manifest: M
|
||||
source?: RunTriggerSource
|
||||
}): Promise<{ automationRunId: string }> => {
|
||||
const { automateRunTrigger } = deps
|
||||
const { revisionId, manifest } = params
|
||||
const { revisionId, manifest, source = RunTriggerSource.Automatic } = params
|
||||
|
||||
if (!isVersionCreatedTriggerManifest(manifest)) {
|
||||
throw new AutomateInvalidTriggerError(
|
||||
@@ -302,7 +304,9 @@ export const triggerAutomationRevisionRun =
|
||||
await AutomateRunsEmitter.emit(AutomateRunsEmitter.events.Created, {
|
||||
run: automationRun,
|
||||
manifests: triggerManifests,
|
||||
automation: automationWithRevision
|
||||
automation: automationWithRevision,
|
||||
source,
|
||||
triggerType: manifest.triggerType
|
||||
})
|
||||
|
||||
return { automationRunId: automationRun.id }
|
||||
@@ -392,13 +396,18 @@ export const ensureRunConditions =
|
||||
async function composeTriggerData(params: {
|
||||
projectId: string
|
||||
manifest: BaseTriggerManifest
|
||||
// TODO: Q Gergo: What's going on here? Why do we pass in extra unrelated triggers?
|
||||
triggerDefinitions: AutomationTriggerDefinitionRecord[]
|
||||
}): Promise<BaseTriggerManifest[]> {
|
||||
const { projectId, manifest, triggerDefinitions } = params
|
||||
|
||||
const manifests: BaseTriggerManifest[] = [{ ...manifest }]
|
||||
|
||||
/**
|
||||
* The reason why we collect multiple triggers, even tho there's only one:
|
||||
* - We want to collect the current context (all active versions of all triggers) at the time when the run is triggered,
|
||||
* cause once the function already runs, there may be new versions already
|
||||
*/
|
||||
|
||||
if (triggerDefinitions.length > 1) {
|
||||
const associatedTriggers = triggerDefinitions.filter((t) => {
|
||||
if (t.triggerType !== manifest.triggerType) return false
|
||||
@@ -492,15 +501,17 @@ export const manuallyTriggerAutomation =
|
||||
}
|
||||
|
||||
// Trigger "model version created"
|
||||
return await triggerFunction({
|
||||
const { automationRunId } = await triggerFunction({
|
||||
revisionId: triggerDefs[0].automationRevisionId,
|
||||
manifest: <VersionCreatedTriggerManifest>{
|
||||
projectId,
|
||||
modelId: latestCommit.branchId,
|
||||
versionId: latestCommit.id,
|
||||
triggerType: VersionCreationTriggerType
|
||||
}
|
||||
},
|
||||
source: RunTriggerSource.Manual
|
||||
})
|
||||
return { automationRunId }
|
||||
}
|
||||
|
||||
export type CreateTestAutomationRunDeps = {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
AutomationTriggerType,
|
||||
BaseTriggerManifest,
|
||||
LiveAutomation,
|
||||
RunTriggerSource,
|
||||
VersionCreatedTriggerManifest,
|
||||
VersionCreationTriggerType,
|
||||
isVersionCreatedTriggerManifest
|
||||
@@ -294,7 +295,8 @@ const { FF_AUTOMATE_MODULE_ENABLED } = Environment.getFeatureFlags()
|
||||
versionId: cryptoRandomString({ length: 10 }),
|
||||
triggerType: VersionCreationTriggerType,
|
||||
modelId: cryptoRandomString({ length: 10 })
|
||||
}
|
||||
},
|
||||
source: RunTriggerSource.Manual
|
||||
})
|
||||
throw 'this should have thrown'
|
||||
} catch (error) {
|
||||
@@ -378,7 +380,8 @@ const { FF_AUTOMATE_MODULE_ENABLED } = Environment.getFeatureFlags()
|
||||
versionId: version.id,
|
||||
modelId: trigger.triggeringId,
|
||||
triggerType: trigger.triggerType
|
||||
}
|
||||
},
|
||||
source: RunTriggerSource.Manual
|
||||
})
|
||||
|
||||
const storedRun = await getFullAutomationRunById(automationRunId)
|
||||
@@ -468,7 +471,8 @@ const { FF_AUTOMATE_MODULE_ENABLED } = Environment.getFeatureFlags()
|
||||
versionId: version.id,
|
||||
modelId: trigger.triggeringId,
|
||||
triggerType: trigger.triggerType
|
||||
}
|
||||
},
|
||||
source: RunTriggerSource.Manual
|
||||
})
|
||||
|
||||
const storedRun = await getFullAutomationRunById(automationRunId)
|
||||
|
||||
@@ -344,7 +344,6 @@ export enum AutomateRunStatus {
|
||||
}
|
||||
|
||||
export enum AutomateRunTriggerType {
|
||||
TestType = 'TEST_TYPE',
|
||||
VersionCreated = 'VERSION_CREATED'
|
||||
}
|
||||
|
||||
@@ -1845,7 +1844,7 @@ export type ProjectAutomationMutations = {
|
||||
* Trigger an automation with a fake "version created" trigger. The "version created" will
|
||||
* just refer to the last version of the model.
|
||||
*/
|
||||
trigger: Scalars['Boolean'];
|
||||
trigger: Scalars['String'];
|
||||
update: Automation;
|
||||
};
|
||||
|
||||
@@ -4736,7 +4735,7 @@ export type ProjectAutomationMutationsResolvers<ContextType = GraphQLContext, Pa
|
||||
createRevision?: Resolver<ResolversTypes['AutomationRevision'], ParentType, ContextType, RequireFields<ProjectAutomationMutationsCreateRevisionArgs, 'input'>>;
|
||||
createTestAutomation?: Resolver<ResolversTypes['Automation'], ParentType, ContextType, RequireFields<ProjectAutomationMutationsCreateTestAutomationArgs, 'input'>>;
|
||||
createTestAutomationRun?: Resolver<ResolversTypes['TestAutomationRun'], ParentType, ContextType, RequireFields<ProjectAutomationMutationsCreateTestAutomationRunArgs, 'automationId'>>;
|
||||
trigger?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<ProjectAutomationMutationsTriggerArgs, 'automationId'>>;
|
||||
trigger?: Resolver<ResolversTypes['String'], ParentType, ContextType, RequireFields<ProjectAutomationMutationsTriggerArgs, 'automationId'>>;
|
||||
update?: Resolver<ResolversTypes['Automation'], ParentType, ContextType, RequireFields<ProjectAutomationMutationsUpdateArgs, 'input'>>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
@@ -333,7 +333,6 @@ export enum AutomateRunStatus {
|
||||
}
|
||||
|
||||
export enum AutomateRunTriggerType {
|
||||
TestType = 'TEST_TYPE',
|
||||
VersionCreated = 'VERSION_CREATED'
|
||||
}
|
||||
|
||||
@@ -1834,7 +1833,7 @@ export type ProjectAutomationMutations = {
|
||||
* Trigger an automation with a fake "version created" trigger. The "version created" will
|
||||
* just refer to the last version of the model.
|
||||
*/
|
||||
trigger: Scalars['Boolean'];
|
||||
trigger: Scalars['String'];
|
||||
update: Automation;
|
||||
};
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ export async function buildMocksConfig(): Promise<{
|
||||
...(isNullOrUndefined(enabled) ? {} : { enabled })
|
||||
}
|
||||
},
|
||||
trigger: () => true,
|
||||
trigger: () => faker.datatype.string(10),
|
||||
createRevision: () => store.get('AutomationRevision') as any
|
||||
},
|
||||
UserAutomateInfo: {
|
||||
|
||||
@@ -334,7 +334,6 @@ export enum AutomateRunStatus {
|
||||
}
|
||||
|
||||
export enum AutomateRunTriggerType {
|
||||
TestType = 'TEST_TYPE',
|
||||
VersionCreated = 'VERSION_CREATED'
|
||||
}
|
||||
|
||||
@@ -1835,7 +1834,7 @@ export type ProjectAutomationMutations = {
|
||||
* Trigger an automation with a fake "version created" trigger. The "version created" will
|
||||
* just refer to the last version of the model.
|
||||
*/
|
||||
trigger: Scalars['Boolean'];
|
||||
trigger: Scalars['String'];
|
||||
update: Automation;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,3 +11,12 @@ export function ensureError(
|
||||
if (e instanceof Error) return e
|
||||
return new UnexpectedErrorStructureError(fallbackMessage)
|
||||
}
|
||||
|
||||
// this makes sure that a case is breaking in typing and in runtime too
|
||||
export function throwUncoveredError(e: never): never {
|
||||
throw createUncoveredError(e)
|
||||
}
|
||||
|
||||
export function createUncoveredError(e: never) {
|
||||
return new Error(`Uncovered error case ${e}.`)
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
},
|
||||
"files.eol": "\n",
|
||||
"volar.vueserver.maxOldSpaceSize": 4000,
|
||||
"cSpell.words": ["Automations", "Bursty", "mjml"],
|
||||
"cSpell.words": ["Automations", "Bursty", "Insertable", "mjml"],
|
||||
"tailwindCSS.experimental.configFile": {
|
||||
"packages/frontend-2/tailwind.config.mjs": "packages/frontend-2/**"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user