mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-12 21:29:20 +00:00
feat: Support Checkly group variables (ENG-3478) (#4418)
* feat: checkly group sync * fix: remove scope discriminator * fix: forms * fix: queries * fix: 500 error * fix: update docs * lint: fix * fix: review changes * fix: PR changes * fix: resolve group select UI not clearing --------- Co-authored-by: Scott Wilson <[email protected]>
This commit is contained in:
+46
-2
@@ -5,14 +5,15 @@ import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/Se
|
||||
import { FilterableSelect, FormControl } from "@app/components/v2";
|
||||
import {
|
||||
TChecklyAccount,
|
||||
useChecklyConnectionListAccounts
|
||||
useChecklyConnectionListAccounts,
|
||||
useChecklyConnectionListGroups
|
||||
} from "@app/hooks/api/appConnections/checkly";
|
||||
import { SecretSync } from "@app/hooks/api/secretSyncs";
|
||||
|
||||
import { TSecretSyncForm } from "../schemas";
|
||||
|
||||
export const ChecklySyncFields = () => {
|
||||
const { control, setValue } = useFormContext<
|
||||
const { control, setValue, watch } = useFormContext<
|
||||
TSecretSyncForm & { destination: SecretSync.Checkly }
|
||||
>();
|
||||
|
||||
@@ -25,12 +26,24 @@ export const ChecklySyncFields = () => {
|
||||
}
|
||||
);
|
||||
|
||||
const accountId = watch("destinationConfig.accountId");
|
||||
|
||||
const { data: groups = [], isPending: isGroupsLoading } = useChecklyConnectionListGroups(
|
||||
connectionId,
|
||||
accountId,
|
||||
{
|
||||
enabled: Boolean(connectionId && accountId)
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SecretSyncConnectionField
|
||||
onChange={() => {
|
||||
setValue("destinationConfig.accountId", "");
|
||||
setValue("destinationConfig.accountName", "");
|
||||
setValue("destinationConfig.groupId", undefined);
|
||||
setValue("destinationConfig.groupName", undefined);
|
||||
}}
|
||||
/>
|
||||
<Controller
|
||||
@@ -60,6 +73,37 @@ export const ChecklySyncFields = () => {
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="destinationConfig.groupId"
|
||||
control={control}
|
||||
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
label="Select a group"
|
||||
isOptional
|
||||
helperText="If provided, secrets will be scoped to a check group instead"
|
||||
tooltipClassName="max-w-md"
|
||||
>
|
||||
<FilterableSelect
|
||||
isLoading={isGroupsLoading && Boolean(connectionId)}
|
||||
isDisabled={!connectionId}
|
||||
isClearable
|
||||
value={groups.find((p) => p.id === value) ?? null}
|
||||
onChange={(option) => {
|
||||
const v = option as SingleValue<TChecklyAccount>;
|
||||
onChange(v?.id ?? null);
|
||||
setValue("destinationConfig.groupName", v?.name ?? undefined);
|
||||
}}
|
||||
options={groups}
|
||||
placeholder="Select a group..."
|
||||
getOptionLabel={(option) => option.name}
|
||||
getOptionValue={(option) => option.id}
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+11
-2
@@ -6,7 +6,16 @@ import { SecretSync } from "@app/hooks/api/secretSyncs";
|
||||
|
||||
export const ChecklySyncReviewFields = () => {
|
||||
const { watch } = useFormContext<TSecretSyncForm & { destination: SecretSync.Checkly }>();
|
||||
const accountName = watch("destinationConfig.accountName");
|
||||
const config = watch("destinationConfig");
|
||||
|
||||
return <GenericFieldLabel label="Account">{accountName}</GenericFieldLabel>;
|
||||
return (
|
||||
<>
|
||||
<GenericFieldLabel label="Account">
|
||||
{config.accountName ?? config.accountId}
|
||||
</GenericFieldLabel>
|
||||
{config.groupId && (
|
||||
<GenericFieldLabel label="Group">{config.groupName ?? config.groupId}</GenericFieldLabel>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+9
-1
@@ -8,7 +8,15 @@ export const ChecklySyncDestinationSchema = BaseSecretSyncSchema().merge(
|
||||
destination: z.literal(SecretSync.Checkly),
|
||||
destinationConfig: z.object({
|
||||
accountId: z.string(),
|
||||
accountName: z.string()
|
||||
accountName: z.string(),
|
||||
groupId: z
|
||||
.string()
|
||||
.nullish()
|
||||
.transform((val) => val || undefined),
|
||||
groupName: z
|
||||
.string()
|
||||
.nullish()
|
||||
.transform((val) => val || undefined)
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
@@ -8,7 +8,9 @@ import { TChecklyAccount } from "./types";
|
||||
const checklyConnectionKeys = {
|
||||
all: [...appConnectionKeys.all, "checkly"] as const,
|
||||
listAccounts: (connectionId: string) =>
|
||||
[...checklyConnectionKeys.all, "workspace-scopes", connectionId] as const
|
||||
[...checklyConnectionKeys.all, "workspace-scopes", connectionId] as const,
|
||||
listGroups: (connectionId: string, accountId: string) =>
|
||||
[...checklyConnectionKeys.all, "groups", connectionId, accountId] as const
|
||||
};
|
||||
|
||||
export const useChecklyConnectionListAccounts = (
|
||||
@@ -35,3 +37,29 @@ export const useChecklyConnectionListAccounts = (
|
||||
...options
|
||||
});
|
||||
};
|
||||
|
||||
export const useChecklyConnectionListGroups = (
|
||||
connectionId: string,
|
||||
accountId: string,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
TChecklyAccount[],
|
||||
unknown,
|
||||
TChecklyAccount[],
|
||||
ReturnType<typeof checklyConnectionKeys.listGroups>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: checklyConnectionKeys.listGroups(connectionId, accountId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{ groups: TChecklyAccount[] }>(
|
||||
`/api/v1/app-connections/checkly/${connectionId}/accounts/${accountId}/groups`
|
||||
);
|
||||
|
||||
return data.groups;
|
||||
},
|
||||
...options
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,11 +3,17 @@ import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { SecretSync } from "@app/hooks/api/secretSyncs";
|
||||
import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
|
||||
|
||||
export enum ChecklySyncScope {
|
||||
Global = "global",
|
||||
Group = "group"
|
||||
}
|
||||
export type TChecklySync = TRootSecretSync & {
|
||||
destination: SecretSync.Checkly;
|
||||
destinationConfig: {
|
||||
accountId: string;
|
||||
accountName: string;
|
||||
groupId?: string;
|
||||
groupName?: string;
|
||||
};
|
||||
connection: {
|
||||
app: AppConnection.Checkly;
|
||||
|
||||
+2
-2
@@ -175,8 +175,8 @@ export const getSecretSyncDestinationColValues = (secretSync: TSecretSync) => {
|
||||
secondaryText = "Railway Project";
|
||||
break;
|
||||
case SecretSync.Checkly:
|
||||
primaryText = destinationConfig.accountName;
|
||||
secondaryText = "Checkly Account";
|
||||
primaryText = destinationConfig.accountName || destinationConfig.accountId;
|
||||
secondaryText = destinationConfig.groupName || destinationConfig.groupId || "Checkly Account";
|
||||
break;
|
||||
case SecretSync.Supabase:
|
||||
primaryText = destinationConfig.projectName;
|
||||
|
||||
+8
-1
@@ -8,5 +8,12 @@ type Props = {
|
||||
export const ChecklySyncDestinationSection = ({ secretSync }: Props) => {
|
||||
const { destinationConfig } = secretSync;
|
||||
|
||||
return <GenericFieldLabel label="Account">{destinationConfig.accountName}</GenericFieldLabel>;
|
||||
return (
|
||||
<>
|
||||
<GenericFieldLabel label="Account">{destinationConfig.accountName}</GenericFieldLabel>
|
||||
{destinationConfig.groupId && (
|
||||
<GenericFieldLabel label="Group">{destinationConfig.groupName}</GenericFieldLabel>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user