diff --git a/backend/src/integrations/sync.ts b/backend/src/integrations/sync.ts index bfa559c74..331dadee1 100644 --- a/backend/src/integrations/sync.ts +++ b/backend/src/integrations/sync.ts @@ -991,7 +991,7 @@ const syncSecretsCircleci = async ({ integration: IIntegration; secrets: any; accessToken: string; -}) => { +}) => { try { const circleciOrganizationDetail = ( await axios.get(`${INTEGRATION_CIRCLECI_API_URL}/v2/me/collaborations`, { @@ -1004,19 +1004,6 @@ const syncSecretsCircleci = async ({ const { slug } = circleciOrganizationDetail; - // get secrets from CircleCI - const getSecretsRes = ( - await axios.get( - `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar`, - { - headers: { - "Circle-Token": accessToken, - "Accept-Encoding": "application/json", - }, - } - ) - ).data?.items; - // inject secrets to CircleCI (one by one) Object.keys(secrets).forEach( async (key) => @@ -1035,6 +1022,20 @@ const syncSecretsCircleci = async ({ ) ); + // get secrets from CircleCI + const getSecretsRes = ( + await axios.get( + `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar`, + { + headers: { + "Circle-Token": accessToken, + "Accept-Encoding": "application/json", + }, + } + ) + ).data?.items; + + // delete secrets from CircleCI getSecretsRes.forEach(async (sec: any) => { if (!(sec.name in secrets)) { await axios.delete( @@ -1042,6 +1043,7 @@ const syncSecretsCircleci = async ({ { headers: { "Circle-Token": accessToken, + "Content-Type": "application/json", }, } ); diff --git a/frontend/src/pages/integrations/[id].tsx b/frontend/src/pages/integrations/[id].tsx index d802e81a8..45314abfd 100644 --- a/frontend/src/pages/integrations/[id].tsx +++ b/frontend/src/pages/integrations/[id].tsx @@ -192,6 +192,9 @@ export default function Integrations() { case 'flyio': link = `${window.location.origin}/integrations/flyio/authorize` break; + case 'circleci': + link = `${window.location.origin}/integrations/circleci/authorize` + break; default: break; } diff --git a/frontend/src/pages/integrations/circleci/authorize.tsx b/frontend/src/pages/integrations/circleci/authorize.tsx new file mode 100644 index 000000000..3033a7d45 --- /dev/null +++ b/frontend/src/pages/integrations/circleci/authorize.tsx @@ -0,0 +1,76 @@ +import { useState } from 'react'; +import { useRouter } from 'next/router'; + +import { getTranslatedServerSideProps } from '../../../components/utilities/withTranslateProps'; +import { + Button, + Card, + CardTitle, + FormControl, + Input, +} from '../../../components/v2'; +import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; + +export default function CircleCICreateIntegrationPage() { + const router = useRouter(); + const [apiKey, setApiKey] = useState(''); + const [apiKeyErrorText, setApiKeyErrorText] = useState(''); + const [isLoading, setIsLoading] = useState(false); + + const handleButtonClick = async () => { + try { + setApiKeyErrorText(''); + if (apiKey.length === 0) { + setApiKeyErrorText('API Key cannot be blank'); + return; + } + + setIsLoading(true); + + const integrationAuth = await saveIntegrationAccessToken({ + workspaceId: localStorage.getItem('projectData.id'), + integration: 'circleci', + accessToken: apiKey + }); + + setIsLoading(false); + + router.push( + `/integrations/circleci/create?integrationAuthId=${integrationAuth._id}` + ); + } catch (err) { + console.error(err); + } + } + + return ( +