feat: support render environment groups (#4327)

* feat: support env groups in render sync

* fix: update doc

* Update backend/src/services/app-connection/render/render-connection-service.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: pr changes

* fix: lint and type check

* fix: changes

* fix: remove secrets

* fix: MAX iterations in render sync

* fix: render sync review fields

* fix: pr changes

* fix: lint

* fix: changes

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
Sid
2025-08-19 16:11:51 +05:30
committed by GitHub
co-authored by greptile-apps[bot]
parent 7748e03612
commit 461deef0d5
19 changed files with 582 additions and 127 deletions
@@ -1,5 +1,8 @@
import { useRenderConnectionListServices } from "@app/hooks/api/appConnections/render";
import { TRenderSync } from "@app/hooks/api/secretSyncs/types/render-sync";
import {
useRenderConnectionListEnvironmentGroups,
useRenderConnectionListServices
} from "@app/hooks/api/appConnections/render";
import { RenderSyncScope, TRenderSync } from "@app/hooks/api/secretSyncs/types/render-sync";
import { getSecretSyncDestinationColValues } from "../helpers";
import { SecretSyncTableCell } from "../SecretSyncTableCell";
@@ -9,21 +12,59 @@ type Props = {
};
export const RenderSyncDestinationCol = ({ secretSync }: Props) => {
const isServiceScope = secretSync.destinationConfig.scope === RenderSyncScope.Service;
const { data: services = [], isPending } = useRenderConnectionListServices(
secretSync.connectionId
secretSync.connectionId,
{
enabled: isServiceScope
}
);
const { primaryText, secondaryText } = getSecretSyncDestinationColValues({
...secretSync,
destinationConfig: {
...secretSync.destinationConfig,
serviceName: services.find((s) => s.id === secretSync.destinationConfig.serviceId)?.name
const { data: groups = [], isPending: isGroupsPending } =
useRenderConnectionListEnvironmentGroups(secretSync.connectionId, { enabled: !isServiceScope });
switch (secretSync.destinationConfig.scope) {
case RenderSyncScope.Service: {
const id = secretSync.destinationConfig.serviceId;
const { primaryText, secondaryText } = getSecretSyncDestinationColValues({
...secretSync,
destinationConfig: {
...secretSync.destinationConfig,
serviceName: services.find((s) => s.id === id)?.name
}
});
if (isPending) {
return (
<SecretSyncTableCell primaryText="Loading service info..." secondaryText="Service" />
);
}
return <SecretSyncTableCell primaryText={primaryText} secondaryText={secondaryText} />;
}
});
case RenderSyncScope.EnvironmentGroup: {
const id = secretSync.destinationConfig.environmentGroupId;
const { primaryText, secondaryText } = getSecretSyncDestinationColValues({
...secretSync,
destinationConfig: {
...secretSync.destinationConfig,
environmentGroupName: groups.find((s) => s.id === id)?.name
}
});
if (isPending) {
return <SecretSyncTableCell primaryText="Loading service info..." secondaryText="Service" />;
if (isGroupsPending) {
return (
<SecretSyncTableCell
primaryText="Loading environment group info..."
secondaryText="Environment Group"
/>
);
}
return <SecretSyncTableCell primaryText={primaryText} secondaryText={secondaryText} />;
}
default:
throw new Error("Unknown render sync destination scope");
}
return <SecretSyncTableCell primaryText={primaryText} secondaryText={secondaryText} />;
};
@@ -8,6 +8,7 @@ import {
} from "@app/hooks/api/secretSyncs/types/github-sync";
import { GitLabSyncScope } from "@app/hooks/api/secretSyncs/types/gitlab-sync";
import { HumanitecSyncScope } from "@app/hooks/api/secretSyncs/types/humanitec-sync";
import { RenderSyncScope } from "@app/hooks/api/secretSyncs/types/render-sync";
// This functional ensures parity across what is displayed in the destination column
// and the values used when search filtering
@@ -125,8 +126,15 @@ export const getSecretSyncDestinationColValues = (secretSync: TSecretSync) => {
secondaryText = destinationConfig.app;
break;
case SecretSync.Render:
primaryText = destinationConfig.serviceName ?? destinationConfig.serviceId;
secondaryText = "Service";
if (destinationConfig.scope === RenderSyncScope.Service) {
primaryText = destinationConfig.serviceName ?? destinationConfig.serviceId;
secondaryText = "Service";
} else {
primaryText =
destinationConfig.environmentGroupName ?? destinationConfig.environmentGroupId;
secondaryText = "Environment Group";
}
break;
case SecretSync.Flyio:
primaryText = destinationConfig.appId;
@@ -1,23 +1,50 @@
import { GenericFieldLabel } from "@app/components/secret-syncs";
import { useRenderConnectionListServices } from "@app/hooks/api/appConnections/render";
import { TRenderSync } from "@app/hooks/api/secretSyncs/types/render-sync";
import {
useRenderConnectionListEnvironmentGroups,
useRenderConnectionListServices
} from "@app/hooks/api/appConnections/render";
import { RenderSyncScope, TRenderSync } from "@app/hooks/api/secretSyncs/types/render-sync";
type Props = {
secretSync: TRenderSync;
};
export const RenderSyncDestinationSection = ({ secretSync }: Props) => {
const isServiceScope = secretSync.destinationConfig.scope === RenderSyncScope.Service;
const { data: services = [], isPending } = useRenderConnectionListServices(
secretSync.connectionId
secretSync.connectionId,
{
enabled: isServiceScope
}
);
const {
destinationConfig: { serviceId }
} = secretSync;
if (isPending) {
return <GenericFieldLabel label="Service">Loading...</GenericFieldLabel>;
const { data: groups = [], isPending: isGroupsPending } =
useRenderConnectionListEnvironmentGroups(secretSync.connectionId, { enabled: !isServiceScope });
switch (secretSync.destinationConfig.scope) {
case RenderSyncScope.Service: {
const id = secretSync.destinationConfig.serviceId;
if (isPending) {
return <GenericFieldLabel label="Service">Loading...</GenericFieldLabel>;
}
const serviceName = services.find((service) => service.id === id)?.name;
return <GenericFieldLabel label="Service">{serviceName ?? id}</GenericFieldLabel>;
}
case RenderSyncScope.EnvironmentGroup: {
const id = secretSync.destinationConfig.environmentGroupId;
if (isGroupsPending) {
return <GenericFieldLabel label="Environment Group">Loading...</GenericFieldLabel>;
}
const envName = groups.find((g) => g.id === id)?.name;
return <GenericFieldLabel label="Environment Group">{envName ?? id}</GenericFieldLabel>;
}
default:
throw new Error("Unknown render sync destination scope");
}
const serviceName = services.find((service) => service.id === serviceId)?.name;
return <GenericFieldLabel label="Service">{serviceName ?? serviceId}</GenericFieldLabel>;
};