Update Checkly groups integration

This commit is contained in:
Tuan Dang
2023-11-02 09:37:36 +02:00
parent f256493cb3
commit 58ff6a43bc
13 changed files with 190 additions and 272 deletions

View File

@@ -1,7 +1,7 @@
import { Request, Response } from "express"; import { Request, Response } from "express";
import { Types } from "mongoose"; import { Types } from "mongoose";
import { standardRequest } from "../../config/request"; import { standardRequest } from "../../config/request";
import { getApps, getTeams, getGroups, revokeAccess } from "../../integrations"; import { getApps, getTeams, revokeAccess } from "../../integrations";
import { Bot, IntegrationAuth, Workspace } from "../../models"; import { Bot, IntegrationAuth, Workspace } from "../../models";
import { EventType } from "../../ee/models"; import { EventType } from "../../ee/models";
import { IntegrationService } from "../../services"; import { IntegrationService } from "../../services";
@@ -10,6 +10,7 @@ import {
ALGORITHM_AES_256_GCM, ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_UTF8, ENCODING_SCHEME_UTF8,
INTEGRATION_BITBUCKET_API_URL, INTEGRATION_BITBUCKET_API_URL,
INTEGRATION_CHECKLY_API_URL,
INTEGRATION_GCP_SECRET_MANAGER, INTEGRATION_GCP_SECRET_MANAGER,
INTEGRATION_NORTHFLANK_API_URL, INTEGRATION_NORTHFLANK_API_URL,
INTEGRATION_QOVERY_API_URL, INTEGRATION_QOVERY_API_URL,
@@ -207,40 +208,6 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
}); });
}; };
/**
* Return list of groups allowed for integration with integration authorization id [integrationAuthId]
* @param req
* @param res
* @returns
*/
export const getIntegrationAuthGroups = async (req: Request, res: Response) => {
const {
params: { integrationAuthId }
} = await validateRequest(reqValidator.GetIntegrationAuthGroupsV1, req);
const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({
integrationAuthId: new ObjectId(integrationAuthId)
});
const { permission } = await getUserProjectPermissions(
req.user._id,
integrationAuth.workspace.toString()
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Integrations
);
const groups = await getGroups({
integrationAuth: integrationAuth,
accessToken: accessToken
});
return res.status(200).send({
groups
});
};
/** /**
* Return list of applications allowed for integration with integration authorization id [integrationAuthId] * Return list of applications allowed for integration with integration authorization id [integrationAuthId]
* @param req * @param req
@@ -378,6 +345,59 @@ export const getIntegrationAuthVercelBranches = async (req: Request, res: Respon
}); });
}; };
/**
* Return list of Checkly groups for a specific user
* @param req
* @param res
*/
export const getIntegrationAuthChecklyGroups = async (req: Request, res: Response) => {
const {
params: { integrationAuthId },
query: { accountId }
} = await validateRequest(reqValidator.GetIntegrationAuthChecklyGroupsV1, req);
const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({
integrationAuthId: new Types.ObjectId(integrationAuthId)
});
const { permission } = await getUserProjectPermissions(
req.user._id,
integrationAuth.workspace.toString()
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Integrations
);
interface ChecklyGroup {
id: number;
name: string;
}
if (accountId && accountId !== "") {
const { data }: { data: ChecklyGroup[] } = (
await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/check-groups`, {
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json",
"X-Checkly-Account": accountId
}
})
);
return res.status(200).send({
groups: data.map((g: ChecklyGroup) => ({
name: g.name,
groupId: g.id,
}))
});
}
return res.status(200).send({
groups: []
});
}
/** /**
* Return list of Qovery Orgs for a specific user * Return list of Qovery Orgs for a specific user
* @param req * @param req

View File

@@ -911,7 +911,7 @@ const getAppsSupabase = async ({ accessToken }: { accessToken: string }) => {
}; };
/** /**
* Return list of projects for the Checkly integration * Return list of accounts for the Checkly integration
* @param {Object} obj * @param {Object} obj
* @param {String} obj.accessToken - api key for the Checkly API * @param {String} obj.accessToken - api key for the Checkly API
* @returns {Object[]} apps - Сheckly accounts * @returns {Object[]} apps - Сheckly accounts

View File

@@ -1,96 +0,0 @@
import {
IIntegrationAuth,
} from "../models";
import {
INTEGRATION_CHECKLY,
INTEGRATION_CHECKLY_API_URL,
} from "../variables";
import { standardRequest } from "../config/request";
interface Group {
name: string;
groupId: string;
}
/**
* Return list of groups for checkly integration authorization [integrationAuth]
* @param {Object} obj
* @param {String} obj.integrationAuth - integration authorization to get groups
* @param {String} obj.accessToken - access token for integration authorization
* @returns {Object[]} groups - groups for integration authorization
* @returns {String} groups.name - name of group
* @returns {String} groups.groupId - id of group
*/
const getGroups = async ({
integrationAuth,
accessToken,
}: {
integrationAuth: IIntegrationAuth;
accessToken: string;
}) => {
let groups: Group[] = [];
switch (integrationAuth.integration) {
case INTEGRATION_CHECKLY:
groups = await getGroupsCheckly({
accessToken,
});
break;
}
return groups;
}
/**
* Return list of groups for Checkly integration
* @param {Object} obj
* @param {String} obj.accessToken - access token for Checkly API
* @returns {Object[]} groups - list of groups in Checkly
* @returns {String} groups.name - name of group
* @returns {String} groups.groupId - id of group
*/
const getGroupsCheckly = async ({
accessToken,
}: {
accessToken: string;
}) => {
let groups: Group[] = [];
// case: fetch account id
const { data } = await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/accounts`, {
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
}
});
const accountId = data.map((a: any) => {
return {
id: a.id,
};
});
// case: fetch list of groups in Checkly
const res = accountId.length > 0 && (
await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/check-groups`, {
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json",
"X-Checkly-Account": accountId[0].id,
}
})
).data;
groups = res.map((g: any) => ({
name: g.name,
groupId: g.id,
}));
return groups;
}
export {
getGroups,
}

View File

@@ -2,7 +2,6 @@ import { exchangeCode } from "./exchange";
import { exchangeRefresh } from "./refresh"; import { exchangeRefresh } from "./refresh";
import { getApps } from "./apps"; import { getApps } from "./apps";
import { getTeams } from "./teams"; import { getTeams } from "./teams";
import { getGroups } from "./groups";
import { revokeAccess } from "./revoke"; import { revokeAccess } from "./revoke";
export { export {
@@ -10,6 +9,5 @@ export {
exchangeRefresh, exchangeRefresh,
getApps, getApps,
getTeams, getTeams,
getGroups,
revokeAccess, revokeAccess,
} }

View File

@@ -2104,7 +2104,7 @@ const syncSecretsSupabase = async ({
}; };
/** /**
* Sync/push [secrets] to Checkly app * Sync/push [secrets] to Checkly app/group
* @param {Object} obj * @param {Object} obj
* @param {IIntegration} obj.integration - integration details * @param {IIntegration} obj.integration - integration details
* @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values)
@@ -2123,6 +2123,8 @@ const syncSecretsCheckly = async ({
}) => { }) => {
if (integration.targetServiceId) { if (integration.targetServiceId) {
// sync secrets to checkly group envars
let getGroupSecretsRes = ( let getGroupSecretsRes = (
await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/check-groups/${integration.targetServiceId}`, { await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/check-groups/${integration.targetServiceId}`, {
headers: { headers: {
@@ -2162,48 +2164,22 @@ const syncSecretsCheckly = async ({
value: secrets[key].value value: secrets[key].value
})); }));
// add secrets await standardRequest.put(
for await (const key of Object.keys(secrets)) { `${INTEGRATION_CHECKLY_API_URL}/v1/check-groups/${integration.targetServiceId}`,
{
if (!(key in getGroupSecretsRes)) { environmentVariables: groupEnvironmentVariables
// case: secret does not exist in checkly group },
// -> add secret {
headers: {
await standardRequest.put( Authorization: `Bearer ${accessToken}`,
`${INTEGRATION_CHECKLY_API_URL}/v1/check-groups/${integration.targetServiceId}`, Accept: "application/json",
{ "X-Checkly-Account": integration.appId
environmentVariables: groupEnvironmentVariables
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json",
"X-Checkly-Account": integration.appId
}
}
);
} else {
// case: secret exists in checkly group
// -> update/set secret
if (secrets[key] !== getGroupSecretsRes[key]) {
await standardRequest.put(
`${INTEGRATION_CHECKLY_API_URL}/v1/check-groups/${integration.targetServiceId}`,
{
environmentVariables: groupEnvironmentVariables
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json",
"X-Checkly-Account": integration.appId
}
}
);
} }
} }
} );
} else { } else {
// sync secrets to checkly global envars
let getSecretsRes = ( let getSecretsRes = (
await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/variables`, { await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/variables`, {
headers: { headers: {

View File

@@ -52,14 +52,6 @@ router.get(
integrationAuthController.getIntegrationAuthTeams integrationAuthController.getIntegrationAuthTeams
); );
router.get(
"/:integrationAuthId/groups",
requireAuth({
acceptedAuthModes: [AuthMode.JWT]
}),
integrationAuthController.getIntegrationAuthGroups
);
router.get( router.get(
"/:integrationAuthId/vercel/branches", "/:integrationAuthId/vercel/branches",
requireAuth({ requireAuth({
@@ -68,6 +60,14 @@ router.get(
integrationAuthController.getIntegrationAuthVercelBranches integrationAuthController.getIntegrationAuthVercelBranches
); );
router.get(
"/:integrationAuthId/checkly/groups",
requireAuth({
acceptedAuthModes: [AuthMode.JWT]
}),
integrationAuthController.getIntegrationAuthChecklyGroups
);
router.get( router.get(
"/:integrationAuthId/qovery/orgs", "/:integrationAuthId/qovery/orgs",
requireAuth({ requireAuth({

View File

@@ -1,11 +1,12 @@
import Redis, { Redis as TRedis } from "ioredis"; import Redis, { Redis as TRedis } from "ioredis";
import { logger } from "../utils/logging";
let redisClient: TRedis | null; let redisClient: TRedis | null;
if (process.env.REDIS_URL) { if (process.env.REDIS_URL) {
redisClient = new Redis(process.env.REDIS_URL as string); redisClient = new Redis(process.env.REDIS_URL as string);
} else { } else {
console.warn("Redis URL not set, skipping Redis initialization."); logger.warn("Redis URL not set, skipping Redis initialization.");
redisClient = null; redisClient = null;
} }

View File

@@ -11,7 +11,6 @@ import {
backfillBots, backfillBots,
backfillEncryptionMetadata, backfillEncryptionMetadata,
backfillIntegration, backfillIntegration,
backfillPermission,
backfillSecretBlindIndexData, backfillSecretBlindIndexData,
backfillSecretFolders, backfillSecretFolders,
backfillSecretVersions, backfillSecretVersions,
@@ -28,6 +27,7 @@ import {
} from "./reencryptData"; } from "./reencryptData";
import { getMongoURL, getNodeEnv, getRedisUrl, getSentryDSN } from "../../config"; import { getMongoURL, getNodeEnv, getRedisUrl, getSentryDSN } from "../../config";
import { initializePassport } from "../auth"; import { initializePassport } from "../auth";
import { logger } from "../logging";
/** /**
* Prepare Infisical upon startup. This includes tasks like: * Prepare Infisical upon startup. This includes tasks like:
@@ -41,7 +41,7 @@ import { initializePassport } from "../auth";
*/ */
export const setup = async () => { export const setup = async () => {
if ((await getRedisUrl()) === undefined || (await getRedisUrl()) === "") { if ((await getRedisUrl()) === undefined || (await getRedisUrl()) === "") {
console.error( logger.error(
"WARNING: Redis is not yet configured. Infisical may not function as expected without it." "WARNING: Redis is not yet configured. Infisical may not function as expected without it."
); );
} }

View File

@@ -117,9 +117,12 @@ export const GetIntegrationAuthVercelBranchesV1 = z.object({
}) })
}); });
export const GetIntegrationAuthGroupsV1 = z.object({ export const GetIntegrationAuthChecklyGroupsV1 = z.object({
params: z.object({ params: z.object({
integrationAuthId: z.string().trim() integrationAuthId: z.string().trim()
}),
query: z.object({
accountId: z.string().trim()
}) })
}); });

View File

@@ -4,12 +4,12 @@ export {
useGetIntegrationAuthApps, useGetIntegrationAuthApps,
useGetIntegrationAuthBitBucketWorkspaces, useGetIntegrationAuthBitBucketWorkspaces,
useGetIntegrationAuthById, useGetIntegrationAuthById,
useGetIntegrationAuthChecklyGroups,
useGetIntegrationAuthNorthflankSecretGroups, useGetIntegrationAuthNorthflankSecretGroups,
useGetIntegrationAuthRailwayEnvironments, useGetIntegrationAuthRailwayEnvironments,
useGetIntegrationAuthRailwayServices, useGetIntegrationAuthRailwayServices,
useGetIntegrationAuthTeamCityBuildConfigs, useGetIntegrationAuthTeamCityBuildConfigs,
useGetIntegrationAuthTeams, useGetIntegrationAuthTeams,
useGetIntegrationAuthVercelBranches, useGetIntegrationAuthVercelBranches,
useSaveIntegrationAccessToken, useSaveIntegrationAccessToken
useGetIntegrationAuthGroups } from "./queries";
} from "./queries";

View File

@@ -6,6 +6,7 @@ import { workspaceKeys } from "../workspace/queries";
import { import {
App, App,
BitBucketWorkspace, BitBucketWorkspace,
ChecklyGroup,
Environment, Environment,
IntegrationAuth, IntegrationAuth,
NorthflankSecretGroup, NorthflankSecretGroup,
@@ -13,8 +14,8 @@ import {
Project, Project,
Service, Service,
Team, Team,
Group, TeamCityBuildConfig
TeamCityBuildConfig} from "./types"; } from "./types";
const integrationAuthKeys = { const integrationAuthKeys = {
getIntegrationAuthById: (integrationAuthId: string) => getIntegrationAuthById: (integrationAuthId: string) =>
@@ -23,8 +24,6 @@ const integrationAuthKeys = {
[{ integrationAuthId, teamId, workspaceSlug }, "integrationAuthApps"] as const, [{ integrationAuthId, teamId, workspaceSlug }, "integrationAuthApps"] as const,
getIntegrationAuthTeams: (integrationAuthId: string) => getIntegrationAuthTeams: (integrationAuthId: string) =>
[{ integrationAuthId }, "integrationAuthTeams"] as const, [{ integrationAuthId }, "integrationAuthTeams"] as const,
getIntegrationAuthGroups: (integrationAuthId: string) =>
[{ integrationAuthId }, "integrationAuthGroups"] as const,
getIntegrationAuthVercelBranches: ({ getIntegrationAuthVercelBranches: ({
integrationAuthId, integrationAuthId,
appId appId
@@ -32,6 +31,14 @@ const integrationAuthKeys = {
integrationAuthId: string; integrationAuthId: string;
appId: string; appId: string;
}) => [{ integrationAuthId, appId }, "integrationAuthVercelBranches"] as const, }) => [{ integrationAuthId, appId }, "integrationAuthVercelBranches"] as const,
getIntegrationAuthChecklyGroups: ({
integrationAuthId,
accountId
}: {
integrationAuthId: string;
accountId: string;
}) =>
[{ integrationAuthId, accountId }, "integrationAuthChecklyGroups"] as const,
getIntegrationAuthQoveryOrgs: (integrationAuthId: string) => getIntegrationAuthQoveryOrgs: (integrationAuthId: string) =>
[{ integrationAuthId }, "integrationAuthQoveryOrgs"] as const, [{ integrationAuthId }, "integrationAuthQoveryOrgs"] as const,
getIntegrationAuthQoveryProjects: ({ getIntegrationAuthQoveryProjects: ({
@@ -128,10 +135,22 @@ const fetchIntegrationAuthTeams = async (integrationAuthId: string) => {
return data.teams; return data.teams;
}; };
const fetchIntegrationAuthGroups = async (integrationAuthId: string) => { const fetchIntegrationAuthChecklyGroups = async ({
const { data } = await apiRequest.get<{ groups: Group[] }>( integrationAuthId,
`/api/v1/integration-auth/${integrationAuthId}/groups` accountId
}: {
integrationAuthId: string;
accountId: string;
}) => {
const { data } = await apiRequest.get<{ groups: ChecklyGroup[] }>(
`/api/v1/integration-auth/${integrationAuthId}/checkly/groups`,
{
params: {
accountId
}
}
); );
return data.groups; return data.groups;
}; };
@@ -422,10 +441,22 @@ export const useGetIntegrationAuthVercelBranches = ({
}); });
}; };
export const useGetIntegrationAuthGroups = (integrationAuthId: string) => { export const useGetIntegrationAuthChecklyGroups = ({
integrationAuthId,
accountId
}: {
integrationAuthId: string;
accountId: string;
}) => {
return useQuery({ return useQuery({
queryKey: integrationAuthKeys.getIntegrationAuthGroups(integrationAuthId), queryKey: integrationAuthKeys.getIntegrationAuthChecklyGroups({
queryFn: () => fetchIntegrationAuthGroups(integrationAuthId), integrationAuthId,
accountId
}),
queryFn: () => fetchIntegrationAuthChecklyGroups({
integrationAuthId,
accountId
}),
enabled: true enabled: true
}); });
}; };

View File

@@ -26,9 +26,9 @@ export type Environment = {
environmentId: string; environmentId: string;
}; };
export type Group = { export type ChecklyGroup = {
name: string; name: string;
groupId: string; groupId: number;
}; };
export type Container = { export type Container = {

View File

@@ -9,8 +9,6 @@ import { motion } from "framer-motion";
import queryString from "query-string"; import queryString from "query-string";
import { import {
Alert,
AlertDescription,
Button, Button,
Card, Card,
CardTitle, CardTitle,
@@ -30,7 +28,7 @@ import {
import { import {
useGetIntegrationAuthApps, useGetIntegrationAuthApps,
useGetIntegrationAuthById, useGetIntegrationAuthById,
useGetIntegrationAuthGroups useGetIntegrationAuthChecklyGroups
} from "../../../hooks/api/integrationAuth"; } from "../../../hooks/api/integrationAuth";
import { useGetWorkspaceById } from "../../../hooks/api/workspace"; import { useGetWorkspaceById } from "../../../hooks/api/workspace";
@@ -45,26 +43,24 @@ export default function ChecklyCreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
const [secretSuffix, setSecretSuffix] = useState("");
const [targetAppId, setTargetAppId] = useState("");
const [targetGroupId, setTargetGroupId] = useState("");
const [isLoading, setIsLoading] = useState(false);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? ""); const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? ""); const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({ const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? "" integrationAuthId: (integrationAuthId as string) ?? ""
}); });
const { data: integrationAuthGroups, isLoading: isintegrationAuthGroupsLoading } = useGetIntegrationAuthGroups( const { data: integrationAuthGroups, isLoading: isintegrationAuthGroupsLoading } = useGetIntegrationAuthChecklyGroups({
(integrationAuthId as string) ?? "" integrationAuthId: (integrationAuthId as string) ?? "",
); accountId: targetAppId
});
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
const [secretSuffix, setSecretSuffix] = useState("");
const [targetApp, setTargetApp] = useState("");
const [targetAppId, setTargetAppId] = useState("");
const [targetGroup, setTargetGroup] = useState("");
const [targetGroupId, setTargetGroupId] = useState("");
const [isLoading, setIsLoading] = useState(false);
useEffect(() => { useEffect(() => {
if (workspace) { if (workspace) {
@@ -73,41 +69,38 @@ export default function ChecklyCreateIntegrationPage() {
}, [workspace]); }, [workspace]);
useEffect(() => { useEffect(() => {
// TODO: handle case where apps can be empty
if (integrationAuthApps) { if (integrationAuthApps) {
if (integrationAuthApps.length > 0) { if (integrationAuthApps.length > 0) {
setTargetApp(integrationAuthApps[0].name); setTargetAppId(integrationAuthApps[0].appId as string);
setTargetAppId(String(integrationAuthApps[0].appId));
} else { } else {
setTargetApp("none"); setTargetAppId("none");
} }
} }
}, [integrationAuthApps]); }, [integrationAuthApps]);
const handleValueChange = (val) => {
const selectedGroup = integrationAuthGroups.find(group => group.name === val);
if (selectedGroup) {
setTargetGroupId(selectedGroup.groupId);
} else {
setTargetGroupId("");
}
setTargetGroup(val);
}
const handleButtonClick = async () => { const handleButtonClick = async () => {
try { try {
if (!integrationAuth?._id) return; if (!integrationAuth?._id) return;
setIsLoading(true); setIsLoading(true);
const targetApp = integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.appId === targetAppId
);
const targetGroup = integrationAuthGroups?.find(
(group) => group.groupId === Number(targetGroupId)
);
if (!targetApp) return;
await mutateAsync({ await mutateAsync({
integrationAuthId: integrationAuth?._id, integrationAuthId: integrationAuth?._id,
isActive: true, isActive: true,
app: targetApp, app: targetApp?.name,
appId: targetAppId, appId: targetApp?.appId,
sourceEnvironment: selectedSourceEnvironment, sourceEnvironment: selectedSourceEnvironment,
targetService: targetGroup, targetService: targetGroup?.name,
targetServiceId: targetGroupId.toString(), targetServiceId: String(targetGroup?.groupId),
secretPath, secretPath,
metadata: { metadata: {
secretSuffix secretSuffix
@@ -127,7 +120,7 @@ export default function ChecklyCreateIntegrationPage() {
selectedSourceEnvironment && selectedSourceEnvironment &&
integrationAuthApps && integrationAuthApps &&
integrationAuthGroups && integrationAuthGroups &&
targetApp ? ( targetAppId ? (
<div className="flex flex-col w-full py-6 items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900"> <div className="flex flex-col w-full py-6 items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
<Head> <Head>
<title>Set Up Checkly Integration</title> <title>Set Up Checkly Integration</title>
@@ -197,48 +190,18 @@ export default function ChecklyCreateIntegrationPage() {
placeholder="Provide a path, default is /" placeholder="Provide a path, default is /"
/> />
</FormControl> </FormControl>
<FormControl label="Checkly Group">
<Select
value={targetGroup}
onValueChange={handleValueChange}
className="w-full border border-mineshaft-500"
>
<SelectItem value="">
Select an option
</SelectItem>
{integrationAuthGroups.length > 0 ? (
integrationAuthGroups.map((integrationAuthGroup) => (
<SelectItem
value={integrationAuthGroup.name}
key={`target-group-${integrationAuthGroup.name}`}
>
{integrationAuthGroup.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-group-none" disabled>
No groups found
</SelectItem>
)}
</Select>
</FormControl>
<Alert className="mb-5" hideTitle="true">
<AlertDescription>
By default environment variables are synced to the global level, select a group above to sync at the Group level.
</AlertDescription>
</Alert>
<FormControl label="Checkly Account"> <FormControl label="Checkly Account">
<Select <Select
value={targetApp} value={targetAppId}
onValueChange={(val) => setTargetApp(val)} onValueChange={(val) => setTargetAppId(val)}
className="w-full border border-mineshaft-500" className="w-full border border-mineshaft-500"
isDisabled={integrationAuthApps.length === 0} isDisabled={integrationAuthApps.length === 0}
> >
{integrationAuthApps.length > 0 ? ( {integrationAuthApps.length > 0 ? (
integrationAuthApps.map((integrationAuthApp) => ( integrationAuthApps.map((integrationAuthApp) => (
<SelectItem <SelectItem
value={integrationAuthApp.name} value={integrationAuthApp.appId as string}
key={`target-app-${integrationAuthApp.name}`} key={`target-app-${integrationAuthApp.appId as string}`}
> >
{integrationAuthApp.name} {integrationAuthApp.name}
</SelectItem> </SelectItem>
@@ -250,6 +213,28 @@ export default function ChecklyCreateIntegrationPage() {
)} )}
</Select> </Select>
</FormControl> </FormControl>
<FormControl label="Checkly Group (Optional)">
<Select
value={targetGroupId}
onValueChange={(val) => setTargetGroupId(val)}
className="w-full border border-mineshaft-500"
>
{integrationAuthGroups.length > 0 ? (
integrationAuthGroups.map((integrationAuthGroup) => (
<SelectItem
value={String(integrationAuthGroup.groupId)}
key={`target-group-${String(integrationAuthGroup.groupId)}`}
>
{integrationAuthGroup.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-group-none">
No groups found
</SelectItem>
)}
</Select>
</FormControl>
</motion.div> </motion.div>
</TabPanel> </TabPanel>
<TabPanel value={TabSections.Options}> <TabPanel value={TabSections.Options}>