mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-10 07:58:15 -05: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 <scottraywilson@gmail.com>
This commit is contained in:
@@ -53,4 +53,36 @@ export const registerChecklyConnectionRouter = async (server: FastifyZodProvider
|
||||
return { accounts };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: `/:connectionId/accounts/:accountId/groups`,
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
connectionId: z.string().uuid(),
|
||||
accountId: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
groups: z
|
||||
.object({
|
||||
name: z.string(),
|
||||
id: z.string()
|
||||
})
|
||||
.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { connectionId, accountId } = req.params;
|
||||
|
||||
const groups = await server.services.appConnection.checkly.listGroups(connectionId, accountId, req.permission);
|
||||
|
||||
return { groups };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ import { AxiosInstance, AxiosRequestConfig, AxiosResponse, HttpStatusCode, isAxi
|
||||
|
||||
import { createRequestClient } from "@app/lib/config/request";
|
||||
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
|
||||
import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
|
||||
|
||||
import { ChecklyConnectionMethod } from "./checkly-connection-constants";
|
||||
import { TChecklyAccount, TChecklyConnectionConfig, TChecklyVariable } from "./checkly-connection-types";
|
||||
@@ -181,6 +182,122 @@ class ChecklyPublicClient {
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
async getCheckGroups(connection: TChecklyConnectionConfig, accountId: string, limit = 50, page = 1) {
|
||||
const res = await this.send<{ id: number; name: string }[]>(connection, {
|
||||
accountId,
|
||||
method: "GET",
|
||||
url: `/v1/check-groups`,
|
||||
params: { limit, page }
|
||||
});
|
||||
|
||||
return res?.map((group) => ({
|
||||
id: group.id.toString(),
|
||||
name: group.name
|
||||
}));
|
||||
}
|
||||
|
||||
async getCheckGroup(connection: TChecklyConnectionConfig, accountId: string, groupId: string) {
|
||||
try {
|
||||
type ChecklyGroupResponse = {
|
||||
id: number;
|
||||
name: string;
|
||||
environmentVariables: Array<{
|
||||
key: string;
|
||||
value: string;
|
||||
locked: boolean;
|
||||
}>;
|
||||
};
|
||||
|
||||
const res = await this.send<ChecklyGroupResponse>(connection, {
|
||||
accountId,
|
||||
method: "GET",
|
||||
url: `/v1/check-groups/${groupId}`
|
||||
});
|
||||
|
||||
if (!res) return null;
|
||||
|
||||
return {
|
||||
id: res.id.toString(),
|
||||
name: res.name,
|
||||
environmentVariables: res.environmentVariables
|
||||
};
|
||||
} catch (error) {
|
||||
if (isAxiosError(error) && error.response?.status === HttpStatusCode.NotFound) {
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateCheckGroupEnvironmentVariables(
|
||||
connection: TChecklyConnectionConfig,
|
||||
accountId: string,
|
||||
groupId: string,
|
||||
environmentVariables: Array<{ key: string; value: string; locked?: boolean }>
|
||||
) {
|
||||
if (environmentVariables.length > 50) {
|
||||
throw new SecretSyncError({
|
||||
message: "Checkly does not support syncing more than 50 variables to Check Group",
|
||||
shouldRetry: false
|
||||
});
|
||||
}
|
||||
|
||||
const apiVariables = environmentVariables.map((v) => ({
|
||||
key: v.key,
|
||||
value: v.value,
|
||||
locked: v.locked ?? false,
|
||||
secret: true
|
||||
}));
|
||||
|
||||
const group = await this.getCheckGroup(connection, accountId, groupId);
|
||||
|
||||
await this.send(connection, {
|
||||
accountId,
|
||||
method: "PUT",
|
||||
url: `/v2/check-groups/${groupId}`,
|
||||
data: { name: group?.name, environmentVariables: apiVariables }
|
||||
});
|
||||
|
||||
return this.getCheckGroup(connection, accountId, groupId);
|
||||
}
|
||||
|
||||
async getCheckGroupEnvironmentVariables(connection: TChecklyConnectionConfig, accountId: string, groupId: string) {
|
||||
const group = await this.getCheckGroup(connection, accountId, groupId);
|
||||
return group?.environmentVariables || [];
|
||||
}
|
||||
|
||||
async upsertCheckGroupEnvironmentVariables(
|
||||
connection: TChecklyConnectionConfig,
|
||||
accountId: string,
|
||||
groupId: string,
|
||||
variables: Array<{ key: string; value: string; locked?: boolean }>
|
||||
) {
|
||||
const existingVars = await this.getCheckGroupEnvironmentVariables(connection, accountId, groupId);
|
||||
const varMap = new Map(existingVars.map((v) => [v.key, v]));
|
||||
|
||||
for (const newVar of variables) {
|
||||
varMap.set(newVar.key, {
|
||||
key: newVar.key,
|
||||
value: newVar.value,
|
||||
locked: newVar.locked ?? false
|
||||
});
|
||||
}
|
||||
|
||||
return this.updateCheckGroupEnvironmentVariables(connection, accountId, groupId, Array.from(varMap.values()));
|
||||
}
|
||||
|
||||
async deleteCheckGroupEnvironmentVariable(
|
||||
connection: TChecklyConnectionConfig,
|
||||
accountId: string,
|
||||
groupId: string,
|
||||
variableKey: string
|
||||
) {
|
||||
const existingVars = await this.getCheckGroupEnvironmentVariables(connection, accountId, groupId);
|
||||
const filteredVars = existingVars.filter((v) => v.key !== variableKey);
|
||||
|
||||
return this.updateCheckGroupEnvironmentVariables(connection, accountId, groupId, filteredVars);
|
||||
}
|
||||
}
|
||||
|
||||
export const ChecklyPublicAPI = new ChecklyPublicClient();
|
||||
|
||||
@@ -24,7 +24,19 @@ export const checklyConnectionService = (getAppConnection: TGetAppConnectionFunc
|
||||
}
|
||||
};
|
||||
|
||||
const listGroups = async (connectionId: string, accountId: string, actor: OrgServiceActor) => {
|
||||
const appConnection = await getAppConnection(AppConnection.Checkly, connectionId, actor);
|
||||
try {
|
||||
const groups = await ChecklyPublicAPI.getCheckGroups(appConnection, accountId);
|
||||
return groups!;
|
||||
} catch (error) {
|
||||
logger.error(error, "Failed to list accounts on Checkly");
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
listAccounts
|
||||
listAccounts,
|
||||
listGroups
|
||||
};
|
||||
};
|
||||
|
||||
@@ -33,3 +33,15 @@ export type TChecklyAccount = {
|
||||
name: string;
|
||||
runtimeId: string;
|
||||
};
|
||||
|
||||
export type TChecklyGroupEnvironmentVariable = {
|
||||
key: string;
|
||||
value: string;
|
||||
locked: boolean;
|
||||
};
|
||||
|
||||
export type TChecklyGroup = {
|
||||
id: string;
|
||||
name: string;
|
||||
environmentVariables?: TChecklyGroupEnvironmentVariable[];
|
||||
};
|
||||
|
||||
@@ -23,56 +23,120 @@ export const ChecklySyncFns = {
|
||||
|
||||
const config = secretSync.destinationConfig;
|
||||
|
||||
const variables = await ChecklyPublicAPI.getVariables(secretSync.connection, config.accountId);
|
||||
if (config.groupId) {
|
||||
// Handle group environment variables
|
||||
const groupVars = await ChecklyPublicAPI.getCheckGroupEnvironmentVariables(
|
||||
secretSync.connection,
|
||||
config.accountId,
|
||||
config.groupId
|
||||
);
|
||||
|
||||
const checklySecrets = Object.fromEntries(variables!.map((variable) => [variable.key, variable]));
|
||||
const checklyGroupSecrets = Object.fromEntries(groupVars.map((variable) => [variable.key, variable]));
|
||||
|
||||
for await (const key of Object.keys(secretMap)) {
|
||||
try {
|
||||
// Prepare all variables to update at once
|
||||
const updatedVariables = { ...checklyGroupSecrets };
|
||||
|
||||
for (const key of Object.keys(secretMap)) {
|
||||
const entry = secretMap[key];
|
||||
|
||||
// If value is empty, we skip the upsert - checkly does not allow empty values
|
||||
// If value is empty, we skip adding it - checkly does not allow empty values
|
||||
if (entry.value.trim() === "") {
|
||||
// Delete the secret from Checkly if its empty
|
||||
// Delete the secret from the group if it's empty
|
||||
if (!disableSecretDeletion) {
|
||||
await ChecklyPublicAPI.deleteVariable(secretSync.connection, config.accountId, {
|
||||
key
|
||||
});
|
||||
delete updatedVariables[key];
|
||||
}
|
||||
continue; // Skip empty values
|
||||
}
|
||||
|
||||
await ChecklyPublicAPI.upsertVariable(secretSync.connection, config.accountId, {
|
||||
// Add or update the variable
|
||||
updatedVariables[key] = {
|
||||
key,
|
||||
value: entry.value,
|
||||
secret: true,
|
||||
locked: true
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Remove secrets that are not in the secretMap if deletion is enabled
|
||||
if (!disableSecretDeletion) {
|
||||
for (const key of Object.keys(checklyGroupSecrets)) {
|
||||
// eslint-disable-next-line no-continue
|
||||
if (!matchesSchema(key, environment?.slug || "", keySchema)) continue;
|
||||
|
||||
if (!secretMap[key]) {
|
||||
delete updatedVariables[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update all group environment variables at once
|
||||
try {
|
||||
await ChecklyPublicAPI.updateCheckGroupEnvironmentVariables(
|
||||
secretSync.connection,
|
||||
config.accountId,
|
||||
config.groupId,
|
||||
Object.values(updatedVariables)
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof SecretSyncError) throw error;
|
||||
|
||||
throw new SecretSyncError({
|
||||
error,
|
||||
secretKey: key
|
||||
secretKey: "group_update"
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Handle global variables (existing logic)
|
||||
const variables = await ChecklyPublicAPI.getVariables(secretSync.connection, config.accountId);
|
||||
|
||||
if (disableSecretDeletion) return;
|
||||
const checklySecrets = Object.fromEntries(variables!.map((variable) => [variable.key, variable]));
|
||||
|
||||
for await (const key of Object.keys(checklySecrets)) {
|
||||
try {
|
||||
// eslint-disable-next-line no-continue
|
||||
if (!matchesSchema(key, environment?.slug || "", keySchema)) continue;
|
||||
for await (const key of Object.keys(secretMap)) {
|
||||
try {
|
||||
const entry = secretMap[key];
|
||||
|
||||
if (!secretMap[key]) {
|
||||
await ChecklyPublicAPI.deleteVariable(secretSync.connection, config.accountId, {
|
||||
key
|
||||
// If value is empty, we skip the upsert - checkly does not allow empty values
|
||||
if (entry.value.trim() === "") {
|
||||
// Delete the secret from Checkly if its empty
|
||||
if (!disableSecretDeletion) {
|
||||
await ChecklyPublicAPI.deleteVariable(secretSync.connection, config.accountId, {
|
||||
key
|
||||
});
|
||||
}
|
||||
continue; // Skip empty values
|
||||
}
|
||||
|
||||
await ChecklyPublicAPI.upsertVariable(secretSync.connection, config.accountId, {
|
||||
key,
|
||||
value: entry.value,
|
||||
secret: true,
|
||||
locked: true
|
||||
});
|
||||
} catch (error) {
|
||||
throw new SecretSyncError({
|
||||
error,
|
||||
secretKey: key
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (disableSecretDeletion) return;
|
||||
|
||||
for await (const key of Object.keys(checklySecrets)) {
|
||||
try {
|
||||
// eslint-disable-next-line no-continue
|
||||
if (!matchesSchema(key, environment?.slug || "", keySchema)) continue;
|
||||
|
||||
if (!secretMap[key]) {
|
||||
await ChecklyPublicAPI.deleteVariable(secretSync.connection, config.accountId, {
|
||||
key
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
throw new SecretSyncError({
|
||||
error,
|
||||
secretKey: key
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
throw new SecretSyncError({
|
||||
error,
|
||||
secretKey: key
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -80,23 +144,54 @@ export const ChecklySyncFns = {
|
||||
async removeSecrets(secretSync: TChecklySyncWithCredentials, secretMap: TSecretMap) {
|
||||
const config = secretSync.destinationConfig;
|
||||
|
||||
const variables = await ChecklyPublicAPI.getVariables(secretSync.connection, config.accountId);
|
||||
if (config.groupId) {
|
||||
// Handle group environment variables
|
||||
const groupVars = await ChecklyPublicAPI.getCheckGroupEnvironmentVariables(
|
||||
secretSync.connection,
|
||||
config.accountId,
|
||||
config.groupId
|
||||
);
|
||||
|
||||
const checklySecrets = Object.fromEntries(variables!.map((variable) => [variable.key, variable]));
|
||||
const checklyGroupSecrets = Object.fromEntries(groupVars.map((variable) => [variable.key, variable]));
|
||||
|
||||
// Filter out the secrets to remove
|
||||
const remainingVariables = Object.keys(checklyGroupSecrets)
|
||||
.filter((key) => !(key in secretMap))
|
||||
.map((key) => checklyGroupSecrets[key]);
|
||||
|
||||
for await (const secret of Object.keys(checklySecrets)) {
|
||||
try {
|
||||
if (secret in secretMap) {
|
||||
await ChecklyPublicAPI.deleteVariable(secretSync.connection, config.accountId, {
|
||||
key: secret
|
||||
});
|
||||
}
|
||||
await ChecklyPublicAPI.updateCheckGroupEnvironmentVariables(
|
||||
secretSync.connection,
|
||||
config.accountId,
|
||||
config.groupId,
|
||||
remainingVariables
|
||||
);
|
||||
} catch (error) {
|
||||
throw new SecretSyncError({
|
||||
error,
|
||||
secretKey: secret
|
||||
secretKey: "group_remove"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Handle global variables (existing logic)
|
||||
const variables = await ChecklyPublicAPI.getVariables(secretSync.connection, config.accountId);
|
||||
|
||||
const checklySecrets = Object.fromEntries(variables!.map((variable) => [variable.key, variable]));
|
||||
|
||||
for await (const secret of Object.keys(checklySecrets)) {
|
||||
try {
|
||||
if (secret in secretMap) {
|
||||
await ChecklyPublicAPI.deleteVariable(secretSync.connection, config.accountId, {
|
||||
key: secret
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
throw new SecretSyncError({
|
||||
error,
|
||||
secretKey: secret
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,7 +11,17 @@ import { TSyncOptionsConfig } from "@app/services/secret-sync/secret-sync-types"
|
||||
|
||||
const ChecklySyncDestinationConfigSchema = z.object({
|
||||
accountId: z.string().min(1, "Account ID is required").max(255, "Account ID must be less than 255 characters"),
|
||||
accountName: z.string().min(1, "Account Name is required").max(255, "Account ID must be less than 255 characters")
|
||||
accountName: z
|
||||
.string()
|
||||
.min(1, "Account Name is required")
|
||||
.max(255, "Account ID must be less than 255 characters")
|
||||
.optional(),
|
||||
groupId: z.string().min(1, "Group ID is required").max(255, "Group ID must be less than 255 characters").optional(),
|
||||
groupName: z
|
||||
.string()
|
||||
.min(1, "Group Name is required")
|
||||
.max(255, "Group Name must be less than 255 characters")
|
||||
.optional()
|
||||
});
|
||||
|
||||
const ChecklySyncOptionsConfig: TSyncOptionsConfig = { canImportSecrets: false };
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 618 KiB After Width: | Height: | Size: 592 KiB |
@@ -37,6 +37,7 @@ description: "Learn how to configure a Checkly Sync for Infisical."
|
||||
|
||||
- **Checkly Connection**: The Checkly Connection to authenticate with.
|
||||
- **Account**: The Checkly account to sync secrets to.
|
||||
- **Group**: The Checkly check group to sync secrets to (Optional).
|
||||
</Step>
|
||||
<Step title="Configure Sync Options">
|
||||
Configure the **Sync Options** to specify how secrets should be synced, then click **Next**.
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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