Add support for service variables to Railway integration, add docs for Railway
@@ -249,7 +249,7 @@ export const getIntegrationAuthVercelBranches = async (req: Request, res: Respon
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return list of available Railway environments for Railway project with
|
* Return list of Railway environments for Railway project with
|
||||||
* id [appId]
|
* id [appId]
|
||||||
* @param req
|
* @param req
|
||||||
* @param res
|
* @param res
|
||||||
@@ -315,6 +315,84 @@ export const getIntegrationAuthRailwayEnvironments = async (req: Request, res: R
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return list of Railway services for Railway project with id
|
||||||
|
* [appId]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
|
export const getIntegrationAuthRailwayServices = async (req: Request, res: Response) => {
|
||||||
|
const { integrationAuthId } = req.params;
|
||||||
|
const appId = req.query.appId as string;
|
||||||
|
|
||||||
|
interface RailwayService {
|
||||||
|
node: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Service {
|
||||||
|
name: string;
|
||||||
|
serviceId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let services: Service[] = [];
|
||||||
|
|
||||||
|
const query = `
|
||||||
|
query project($id: String!) {
|
||||||
|
project(id: $id) {
|
||||||
|
createdAt
|
||||||
|
deletedAt
|
||||||
|
id
|
||||||
|
description
|
||||||
|
expiredAt
|
||||||
|
isPublic
|
||||||
|
isTempProject
|
||||||
|
isUpdatable
|
||||||
|
name
|
||||||
|
prDeploys
|
||||||
|
teamId
|
||||||
|
updatedAt
|
||||||
|
upstreamUrl
|
||||||
|
services {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (appId && appId !== '') {
|
||||||
|
const variables = {
|
||||||
|
id: appId
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: { data: { project: { services: { edges } } } } } = await request.post(INTEGRATION_RAILWAY_API_URL, {
|
||||||
|
query,
|
||||||
|
variables
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${req.accessToken}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
services = edges.map((e: RailwayService) => ({
|
||||||
|
name: e.node.name,
|
||||||
|
serviceId: e.node.id
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
services
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete integration authorization with id [integrationAuthId]
|
* Delete integration authorization with id [integrationAuthId]
|
||||||
* @param req
|
* @param req
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ export const createIntegration = async (req: Request, res: Response) => {
|
|||||||
sourceEnvironment,
|
sourceEnvironment,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
targetEnvironmentId,
|
targetEnvironmentId,
|
||||||
|
targetService,
|
||||||
|
targetServiceId,
|
||||||
owner,
|
owner,
|
||||||
path,
|
path,
|
||||||
region
|
region
|
||||||
@@ -41,12 +43,14 @@ export const createIntegration = async (req: Request, res: Response) => {
|
|||||||
appId,
|
appId,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
targetEnvironmentId,
|
targetEnvironmentId,
|
||||||
|
targetService,
|
||||||
|
targetServiceId,
|
||||||
owner,
|
owner,
|
||||||
path,
|
path,
|
||||||
region,
|
region,
|
||||||
integration: req.integrationAuth.integration,
|
integration: req.integrationAuth.integration,
|
||||||
integrationAuth: new Types.ObjectId(integrationAuthId)
|
integrationAuth: new Types.ObjectId(integrationAuthId)
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
if (integration) {
|
if (integration) {
|
||||||
// trigger event - push secrets
|
// trigger event - push secrets
|
||||||
|
|||||||
@@ -355,10 +355,7 @@ const getAppsRailway = async ({ accessToken }: { accessToken: string }) => {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const variables = {
|
const variables = {};
|
||||||
// userId: '<USER_ID_GOES_HERE>', // Replace with the desired user ID or remove if not needed
|
|
||||||
// teamId: '<TEAM_ID_GOES_HERE>', // Replace with the desired team ID or remove if not needed
|
|
||||||
};
|
|
||||||
|
|
||||||
const { data: { data: { projects: { edges }}} } = await request.post(INTEGRATION_RAILWAY_API_URL, {
|
const { data: { data: { projects: { edges }}} } = await request.post(INTEGRATION_RAILWAY_API_URL, {
|
||||||
query,
|
query,
|
||||||
@@ -367,6 +364,7 @@ const getAppsRailway = async ({ accessToken }: { accessToken: string }) => {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${accessToken}`,
|
'Authorization': `Bearer ${accessToken}`,
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'Accept-Encoding': 'application/json'
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1179,6 +1179,7 @@ const syncSecretsRailway = async ({
|
|||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
mutation UpsertVariables($input: VariableCollectionUpsertInput!) {
|
mutation UpsertVariables($input: VariableCollectionUpsertInput!) {
|
||||||
variableCollectionUpsert(input: $input)
|
variableCollectionUpsert(input: $input)
|
||||||
@@ -1188,6 +1189,7 @@ const syncSecretsRailway = async ({
|
|||||||
const input = {
|
const input = {
|
||||||
projectId: integration.appId,
|
projectId: integration.appId,
|
||||||
environmentId: integration.targetEnvironmentId,
|
environmentId: integration.targetEnvironmentId,
|
||||||
|
...(integration.targetServiceId ? { serviceId: integration.targetServiceId } : {}),
|
||||||
replace: true,
|
replace: true,
|
||||||
variables: secrets
|
variables: secrets
|
||||||
};
|
};
|
||||||
@@ -1201,6 +1203,7 @@ const syncSecretsRailway = async ({
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${accessToken}`,
|
'Authorization': `Bearer ${accessToken}`,
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'Accept-Encoding': 'application/json'
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ export interface IIntegration {
|
|||||||
environment: string;
|
environment: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
app: string;
|
app: string;
|
||||||
|
appId: string;
|
||||||
owner: string;
|
owner: string;
|
||||||
targetEnvironment: string;
|
targetEnvironment: string;
|
||||||
targetEnvironmentId: string;
|
targetEnvironmentId: string;
|
||||||
appId: string;
|
targetService: string;
|
||||||
|
targetServiceId: string;
|
||||||
path: string;
|
path: string;
|
||||||
region: string;
|
region: string;
|
||||||
integration:
|
integration:
|
||||||
@@ -78,6 +80,16 @@ const integrationSchema = new Schema<IIntegration>(
|
|||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
targetService: {
|
||||||
|
// railway-specific service
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
targetServiceId: {
|
||||||
|
// railway-specific service
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
owner: {
|
owner: {
|
||||||
// github-specific repo owner-login
|
// github-specific repo owner-login
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ router.post( // new: add new integration for integration auth
|
|||||||
body('sourceEnvironment').trim(),
|
body('sourceEnvironment').trim(),
|
||||||
body('targetEnvironment').trim(),
|
body('targetEnvironment').trim(),
|
||||||
body('targetEnvironmentId').trim(),
|
body('targetEnvironmentId').trim(),
|
||||||
|
body('targetService').trim(),
|
||||||
|
body('targetServiceId').trim(),
|
||||||
body('owner').trim(),
|
body('owner').trim(),
|
||||||
body('path').trim(),
|
body('path').trim(),
|
||||||
body('region').trim(),
|
body('region').trim(),
|
||||||
|
|||||||
@@ -125,6 +125,20 @@ router.get(
|
|||||||
integrationAuthController.getIntegrationAuthRailwayEnvironments
|
integrationAuthController.getIntegrationAuthRailwayEnvironments
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/:integrationAuthId/railway/services',
|
||||||
|
requireAuth({
|
||||||
|
acceptedAuthModes: ['jwt']
|
||||||
|
}),
|
||||||
|
requireIntegrationAuthorizationAuth({
|
||||||
|
acceptedRoles: [ADMIN, MEMBER]
|
||||||
|
}),
|
||||||
|
param('integrationAuthId').exists().isString(),
|
||||||
|
query('appId').exists().isString(),
|
||||||
|
validateRequest,
|
||||||
|
integrationAuthController.getIntegrationAuthRailwayServices
|
||||||
|
);
|
||||||
|
|
||||||
router.delete(
|
router.delete(
|
||||||
'/:integrationAuthId',
|
'/:integrationAuthId',
|
||||||
requireAuth({
|
requireAuth({
|
||||||
|
|||||||
|
After Width: | Height: | Size: 499 KiB |
|
After Width: | Height: | Size: 587 KiB |
|
After Width: | Height: | Size: 496 KiB |
|
After Width: | Height: | Size: 570 KiB |
|
After Width: | Height: | Size: 391 KiB |
|
Before Width: | Height: | Size: 424 KiB After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
title: "Railway"
|
||||||
|
description: "How to automatically sync secrets from Infisical into your Railway projects and services"
|
||||||
|
---
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- Set up and add envars to [Infisical Cloud](https://app.infisical.com)
|
||||||
|
|
||||||
|
|
||||||
|
## Navigate to your project's integrations tab
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Enter your Railway API Token
|
||||||
|
|
||||||
|
Obtain a Railway API Token in your Railway [Account Settings > Tokens](https://railway.app/account/tokens).
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
<Note>
|
||||||
|
If this is your first time creating a Railway API token, then you'll be prompted to join
|
||||||
|
Railway's Private Boarding Beta program on the Railway Account Settings > Tokens page.
|
||||||
|
|
||||||
|
Note that Railway project tokens will not work for this integration since they don't work with
|
||||||
|
Railway's Public API.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
Press on the Railway tile and input your Railway API Key to grant Infisical access to your Railway account.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
<Info>
|
||||||
|
If this is your project's first cloud integration, then you'll have to grant
|
||||||
|
Infisical access to your project's environment variables. Although this step
|
||||||
|
breaks E2EE, it's necessary for Infisical to sync the environment variables to
|
||||||
|
the cloud platform.
|
||||||
|
</Info>
|
||||||
|
|
||||||
|
## Start integration
|
||||||
|
|
||||||
|
Select which Infisical environment secrets you want to sync to which Railway project and environment (and optionally service). Lastly, press create integration to start syncing secrets to Railway.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
<Note>
|
||||||
|
Infisical integrates with both Railway's [shared variables](https://blog.railway.app/p/shared-variables-release) at the project environment level as well as service variables at the service level.
|
||||||
|
|
||||||
|
To sync secrets to a specific service in a project, you can select a service from the Railway Service dropdown; otherwise, leaving it empty will sync secrets to the shared variables of that project.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi
|
|||||||
| [Vercel](/integrations/cloud/vercel) | Cloud | Available |
|
| [Vercel](/integrations/cloud/vercel) | Cloud | Available |
|
||||||
| [Netlify](/integrations/cloud/netlify) | Cloud | Available |
|
| [Netlify](/integrations/cloud/netlify) | Cloud | Available |
|
||||||
| [Render](/integrations/cloud/render) | Cloud | Available |
|
| [Render](/integrations/cloud/render) | Cloud | Available |
|
||||||
|
| [Railway](/integrations/cloud/railway) | Cloud | Available |
|
||||||
| [Fly.io](/integrations/cloud/flyio) | Cloud | Available |
|
| [Fly.io](/integrations/cloud/flyio) | Cloud | Available |
|
||||||
| [AWS Parameter Store](/integrations/cloud/aws-parameter-store) | Cloud | Available |
|
| [AWS Parameter Store](/integrations/cloud/aws-parameter-store) | Cloud | Available |
|
||||||
| [AWS Secret Manager](/integrations/cloud/aws-secret-manager) | Cloud | Available |
|
| [AWS Secret Manager](/integrations/cloud/aws-secret-manager) | Cloud | Available |
|
||||||
|
|||||||
@@ -149,6 +149,7 @@
|
|||||||
"integrations/cloud/vercel",
|
"integrations/cloud/vercel",
|
||||||
"integrations/cloud/netlify",
|
"integrations/cloud/netlify",
|
||||||
"integrations/cloud/render",
|
"integrations/cloud/render",
|
||||||
|
"integrations/cloud/railway",
|
||||||
"integrations/cloud/flyio",
|
"integrations/cloud/flyio",
|
||||||
"integrations/cloud/azure-key-vault",
|
"integrations/cloud/azure-key-vault",
|
||||||
"integrations/cicd/githubactions",
|
"integrations/cicd/githubactions",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const integrationSlugNameMapping: Mapping = {
|
|||||||
'github': 'GitHub',
|
'github': 'GitHub',
|
||||||
'gitlab': 'GitLab',
|
'gitlab': 'GitLab',
|
||||||
'render': 'Render',
|
'render': 'Render',
|
||||||
|
'railway': 'Railway',
|
||||||
'flyio': 'Fly.io',
|
'flyio': 'Fly.io',
|
||||||
'circleci': 'CircleCI',
|
'circleci': 'CircleCI',
|
||||||
'travisci': 'TravisCI'
|
'travisci': 'TravisCI'
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ type Props = {
|
|||||||
handleDeleteIntegration: (args: { integration: Integration }) => void;
|
handleDeleteIntegration: (args: { integration: Integration }) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: refactor
|
||||||
const IntegrationTile = ({
|
const IntegrationTile = ({
|
||||||
integration,
|
integration,
|
||||||
integrations,
|
integrations,
|
||||||
@@ -55,7 +56,6 @@ const IntegrationTile = ({
|
|||||||
handleDeleteIntegration
|
handleDeleteIntegration
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
|
||||||
// set initial environment. This find will only execute when component is mounting
|
|
||||||
const [integrationEnvironment, setIntegrationEnvironment] = useState<Props['environments'][0]>(
|
const [integrationEnvironment, setIntegrationEnvironment] = useState<Props['environments'][0]>(
|
||||||
environments.find(({ slug }) => slug === integration?.environment) || {
|
environments.find(({ slug }) => slug === integration?.environment) || {
|
||||||
name: '',
|
name: '',
|
||||||
@@ -176,6 +176,21 @@ const IntegrationTile = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
case 'railway':
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="mb-2 text-xs font-semibold text-gray-400">ENVIRONMENT</div>
|
||||||
|
<ListBox
|
||||||
|
data={
|
||||||
|
!integration.isActive
|
||||||
|
? ['Production', 'Deploy previews', 'Branch deploys', 'Local development']
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
isSelected={integration.targetEnvironment}
|
||||||
|
onChange={setIntegrationTargetEnvironment}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return <div />;
|
return <div />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export {
|
export {
|
||||||
useGetIntegrationAuthApps,
|
useGetIntegrationAuthApps,
|
||||||
useGetIntegrationAuthById,
|
useGetIntegrationAuthById,
|
||||||
|
useGetIntegrationAuthRailwayEnvironments,
|
||||||
|
useGetIntegrationAuthRailwayServices,
|
||||||
useGetIntegrationAuthTeams,
|
useGetIntegrationAuthTeams,
|
||||||
useGetIntegrationAuthVercelBranches,
|
useGetIntegrationAuthVercelBranches} from './queries';
|
||||||
useGetRailwayEnvironments
|
|
||||||
} from './queries';
|
|
||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
App,
|
App,
|
||||||
Environment,
|
Environment,
|
||||||
IntegrationAuth,
|
IntegrationAuth,
|
||||||
|
Service,
|
||||||
Team
|
Team
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
@@ -27,6 +28,13 @@ const integrationAuthKeys = {
|
|||||||
integrationAuthId: string;
|
integrationAuthId: string;
|
||||||
appId: string;
|
appId: string;
|
||||||
}) => [{ integrationAuthId, appId }, 'integrationAuthRailwayEnvironments'] as const,
|
}) => [{ integrationAuthId, appId }, 'integrationAuthRailwayEnvironments'] as const,
|
||||||
|
getIntegrationAuthRailwayServices: ({
|
||||||
|
integrationAuthId,
|
||||||
|
appId
|
||||||
|
}: {
|
||||||
|
integrationAuthId: string;
|
||||||
|
appId: string;
|
||||||
|
}) => [{ integrationAuthId, appId }, 'integrationAuthRailwayServices'] as const
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchIntegrationAuthById = async (integrationAuthId: string) => {
|
const fetchIntegrationAuthById = async (integrationAuthId: string) => {
|
||||||
@@ -86,6 +94,22 @@ const fetchIntegrationAuthRailwayEnvironments = async ({
|
|||||||
return environments;
|
return environments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchIntegrationAuthRailwayServices = async ({
|
||||||
|
integrationAuthId,
|
||||||
|
appId
|
||||||
|
}: {
|
||||||
|
integrationAuthId: string;
|
||||||
|
appId: string;
|
||||||
|
}) => {
|
||||||
|
const { data: { services } } = await apiRequest.get<{ services: Service[] }>(`/api/v1/integration-auth/${integrationAuthId}/railway/services`, {
|
||||||
|
params: {
|
||||||
|
appId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
export const useGetIntegrationAuthById = (integrationAuthId: string) => {
|
export const useGetIntegrationAuthById = (integrationAuthId: string) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: integrationAuthKeys.getIntegrationAuthById(integrationAuthId),
|
queryKey: integrationAuthKeys.getIntegrationAuthById(integrationAuthId),
|
||||||
@@ -139,7 +163,7 @@ export const useGetIntegrationAuthVercelBranches = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useGetRailwayEnvironments = ({
|
export const useGetIntegrationAuthRailwayEnvironments = ({
|
||||||
integrationAuthId,
|
integrationAuthId,
|
||||||
appId
|
appId
|
||||||
}: {
|
}: {
|
||||||
@@ -158,3 +182,23 @@ export const useGetRailwayEnvironments = ({
|
|||||||
enabled: true
|
enabled: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useGetIntegrationAuthRailwayServices = ({
|
||||||
|
integrationAuthId,
|
||||||
|
appId
|
||||||
|
}: {
|
||||||
|
integrationAuthId: string;
|
||||||
|
appId: string;
|
||||||
|
}) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: integrationAuthKeys.getIntegrationAuthRailwayServices({
|
||||||
|
integrationAuthId,
|
||||||
|
appId,
|
||||||
|
}),
|
||||||
|
queryFn: () => fetchIntegrationAuthRailwayServices({
|
||||||
|
integrationAuthId,
|
||||||
|
appId,
|
||||||
|
}),
|
||||||
|
enabled: true
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -21,3 +21,8 @@ export type Environment = {
|
|||||||
name: string;
|
name: string;
|
||||||
environmentId: string;
|
environmentId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Service = {
|
||||||
|
name: string;
|
||||||
|
serviceId: string;
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ interface Props {
|
|||||||
sourceEnvironment: string;
|
sourceEnvironment: string;
|
||||||
targetEnvironment: string | null;
|
targetEnvironment: string | null;
|
||||||
targetEnvironmentId: string | null;
|
targetEnvironmentId: string | null;
|
||||||
|
targetService: string | null;
|
||||||
|
targetServiceId: string | null;
|
||||||
owner: string | null;
|
owner: string | null;
|
||||||
path: string | null;
|
path: string | null;
|
||||||
region: string | null;
|
region: string | null;
|
||||||
@@ -26,6 +28,8 @@ const createIntegration = ({
|
|||||||
sourceEnvironment,
|
sourceEnvironment,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
targetEnvironmentId,
|
targetEnvironmentId,
|
||||||
|
targetService,
|
||||||
|
targetServiceId,
|
||||||
owner,
|
owner,
|
||||||
path,
|
path,
|
||||||
region
|
region
|
||||||
@@ -43,6 +47,8 @@ const createIntegration = ({
|
|||||||
sourceEnvironment,
|
sourceEnvironment,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
targetEnvironmentId,
|
targetEnvironmentId,
|
||||||
|
targetService,
|
||||||
|
targetServiceId,
|
||||||
owner,
|
owner,
|
||||||
path,
|
path,
|
||||||
region
|
region
|
||||||
|
|||||||
@@ -99,6 +99,8 @@ export default function AWSParameterStoreCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path,
|
path,
|
||||||
region: selectedAWSRegion
|
region: selectedAWSRegion
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ export default function AWSSecretManagerCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: selectedAWSRegion
|
region: selectedAWSRegion
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ export default function AzureKeyVaultCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ export default function CircleCICreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null,
|
region: null,
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ export default function FlyioCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: targetApp.owner,
|
owner: targetApp.owner,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ export default function HerokuCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ export default function NetlifyCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
useGetIntegrationAuthApps,
|
useGetIntegrationAuthApps,
|
||||||
useGetIntegrationAuthById,
|
useGetIntegrationAuthById,
|
||||||
useGetRailwayEnvironments
|
useGetIntegrationAuthRailwayEnvironments,
|
||||||
|
useGetIntegrationAuthRailwayServices
|
||||||
} from '../../../hooks/api/integrationAuth';
|
} from '../../../hooks/api/integrationAuth';
|
||||||
import { useGetWorkspaceById } from '../../../hooks/api/workspace';
|
import { useGetWorkspaceById } from '../../../hooks/api/workspace';
|
||||||
import createIntegration from "../../api/integrations/createIntegration";
|
import createIntegration from "../../api/integrations/createIntegration";
|
||||||
@@ -24,6 +25,8 @@ export default function RailwayCreateIntegrationPage() {
|
|||||||
|
|
||||||
const [targetAppId, setTargetAppId] = useState('');
|
const [targetAppId, setTargetAppId] = useState('');
|
||||||
const [targetEnvironmentId, setTargetEnvironmentId] = useState('');
|
const [targetEnvironmentId, setTargetEnvironmentId] = useState('');
|
||||||
|
const [targetServiceId, setTargetServiceId] = useState('');
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState('');
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState('');
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
@@ -33,8 +36,11 @@ export default function RailwayCreateIntegrationPage() {
|
|||||||
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
|
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
|
||||||
integrationAuthId: integrationAuthId as string ?? ''
|
integrationAuthId: integrationAuthId as string ?? ''
|
||||||
});
|
});
|
||||||
|
const { data: targetEnvironments } = useGetIntegrationAuthRailwayEnvironments({
|
||||||
const { data: targetEnvironments } = useGetRailwayEnvironments({
|
integrationAuthId: integrationAuthId as string ?? '',
|
||||||
|
appId: targetAppId
|
||||||
|
});
|
||||||
|
const { data: targetServices } = useGetIntegrationAuthRailwayServices({
|
||||||
integrationAuthId: integrationAuthId as string ?? '',
|
integrationAuthId: integrationAuthId as string ?? '',
|
||||||
appId: targetAppId
|
appId: targetAppId
|
||||||
});
|
});
|
||||||
@@ -65,6 +71,12 @@ export default function RailwayCreateIntegrationPage() {
|
|||||||
}
|
}
|
||||||
}, [targetEnvironments]);
|
}, [targetEnvironments]);
|
||||||
|
|
||||||
|
const filteredServices = targetServices
|
||||||
|
?.concat({
|
||||||
|
name: '',
|
||||||
|
serviceId: ''
|
||||||
|
});
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@@ -76,6 +88,8 @@ export default function RailwayCreateIntegrationPage() {
|
|||||||
|
|
||||||
if (!targetApp || !targetApp.appId || !targetEnvironment) return;
|
if (!targetApp || !targetApp.appId || !targetEnvironment) return;
|
||||||
|
|
||||||
|
const targetService = targetServices?.find((service) => service.serviceId === targetServiceId);
|
||||||
|
|
||||||
await createIntegration({
|
await createIntegration({
|
||||||
integrationAuthId: integrationAuth?._id,
|
integrationAuthId: integrationAuth?._id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
@@ -84,6 +98,8 @@ export default function RailwayCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: targetEnvironment.name,
|
targetEnvironment: targetEnvironment.name,
|
||||||
targetEnvironmentId: targetEnvironment.environmentId,
|
targetEnvironmentId: targetEnvironment.environmentId,
|
||||||
|
targetService: targetService ? targetService.name : null,
|
||||||
|
targetServiceId: targetService ? targetService.serviceId : null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
@@ -99,7 +115,7 @@ export default function RailwayCreateIntegrationPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return workspace && selectedSourceEnvironment && integrationAuthApps && targetEnvironments ? (
|
return workspace && selectedSourceEnvironment && integrationAuthApps && targetEnvironments && filteredServices ? (
|
||||||
<div className="h-full w-full flex justify-center items-center">
|
<div className="h-full w-full flex justify-center items-center">
|
||||||
<Card className="max-w-md p-8 rounded-md">
|
<Card className="max-w-md p-8 rounded-md">
|
||||||
<CardTitle className="text-center">Railway Integration</CardTitle>
|
<CardTitle className="text-center">Railway Integration</CardTitle>
|
||||||
@@ -158,6 +174,19 @@ export default function RailwayCreateIntegrationPage() {
|
|||||||
)}
|
)}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
<FormControl label="Railway Service (Optional)">
|
||||||
|
<Select
|
||||||
|
value={targetServiceId}
|
||||||
|
onValueChange={(val) => setTargetServiceId(val)}
|
||||||
|
className='w-full border border-mineshaft-500'
|
||||||
|
>
|
||||||
|
{filteredServices.map((targetService) => (
|
||||||
|
<SelectItem value={targetService.serviceId as string} key={`target-service-${targetService.serviceId as string}`}>
|
||||||
|
{targetService.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleButtonClick}
|
onClick={handleButtonClick}
|
||||||
color="mineshaft"
|
color="mineshaft"
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ export default function RenderCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ export default function TravisCICreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path: null,
|
||||||
region: null,
|
region: null,
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
targetEnvironmentId: null,
|
targetEnvironmentId: null,
|
||||||
|
targetService: null,
|
||||||
|
targetServiceId: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
path,
|
path,
|
||||||
region: null
|
region: null
|
||||||
|
|||||||