mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 17:28:18 +00:00
improvements: address feedback/requests
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 441 KiB |
@@ -29,12 +29,18 @@ Prerequisites:
|
|||||||

|
generate api key](/images/integrations/octopus-deploy/integrations-octopus-deploy-generate-api-key.png)
|
||||||
|
|
||||||
|
<Note>If you configure your access token to expire,
|
||||||
|
you will need to generate a new API key for Infisical prior to this date to keep your integration running.</Note>
|
||||||
|
|
||||||
Copy the generated **API Key** and click on the **Close** button.
|
Copy the generated **API Key** and click on the **Close** button.
|
||||||
|
|
||||||

|
copy api key](/images/integrations/octopus-deploy/integrations-octopus-deploy-copy-api-key.png)
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Create a Service Accounts Team and assign your Service Account">
|
<Step title="Create a Service Accounts Team and assign your Service Account">
|
||||||
|
<Note>You can skip creating a new team if you already have an Octopus Deploy team configured with
|
||||||
|
the **Project Contributor** role to assign your Service Account to.</Note>
|
||||||
|
|
||||||
Navigate to **Configuration** > **Teams** and click on the **Add Team** button.
|
Navigate to **Configuration** > **Teams** and click on the **Add Team** button.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
On the **User Roles** tab, click on the **Include User Role** button, add the **Project Contributor** role and click on the **Apply** button.
|
On the **User Roles** tab, click on the **Include User Role** button, and add the **Project Contributor** role. Optionally,
|
||||||
|
click on the **Define Scope** button to further refine what projects your Service Account has access to. Click on the **Apply** button once complete.
|
||||||

|

|
||||||
|
|
||||||
Save your team changes by clicking on the **Save** button.
|
Save your team changes by clicking on the **Save** button.
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
Team,
|
Team,
|
||||||
TeamCityBuildConfig,
|
TeamCityBuildConfig,
|
||||||
TGetIntegrationAuthOctopusDeployScopeValuesDTO,
|
TGetIntegrationAuthOctopusDeployScopeValuesDTO,
|
||||||
TOctopusDeployScopeValues
|
TOctopusDeployVariableSetScopeValues
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
const integrationAuthKeys = {
|
const integrationAuthKeys = {
|
||||||
@@ -503,7 +503,7 @@ const fetchIntegrationAuthOctopusDeployScopeValues = async ({
|
|||||||
spaceId,
|
spaceId,
|
||||||
resourceId
|
resourceId
|
||||||
}: TGetIntegrationAuthOctopusDeployScopeValuesDTO) => {
|
}: TGetIntegrationAuthOctopusDeployScopeValuesDTO) => {
|
||||||
const { data } = await apiRequest.get<TOctopusDeployScopeValues>(
|
const { data } = await apiRequest.get<TOctopusDeployVariableSetScopeValues>(
|
||||||
`/api/v1/integration-auth/${integrationAuthId}/octopus-deploy/scope-values`,
|
`/api/v1/integration-auth/${integrationAuthId}/octopus-deploy/scope-values`,
|
||||||
{ params: { scope, spaceId, resourceId } }
|
{ params: { scope, spaceId, resourceId } }
|
||||||
);
|
);
|
||||||
@@ -799,14 +799,18 @@ export const useGetIntegrationAuthBitBucketWorkspaces = (integrationAuthId: stri
|
|||||||
|
|
||||||
export const useGetIntegrationAuthOctopusDeploySpaces = (integrationAuthId: string) => {
|
export const useGetIntegrationAuthOctopusDeploySpaces = (integrationAuthId: string) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: integrationAuthKeys.getIntegrationAuthBitBucketWorkspaces(integrationAuthId),
|
queryKey: integrationAuthKeys.getIntegrationAuthOctopusDeploySpaces(integrationAuthId),
|
||||||
queryFn: () => fetchIntegrationAuthOctopusDeploySpaces(integrationAuthId)
|
queryFn: () => fetchIntegrationAuthOctopusDeploySpaces(integrationAuthId)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetIntegrationAuthOctopusDeployScopeValues = (
|
export const useGetIntegrationAuthOctopusDeployScopeValues = (
|
||||||
params: TGetIntegrationAuthOctopusDeployScopeValuesDTO,
|
params: TGetIntegrationAuthOctopusDeployScopeValuesDTO,
|
||||||
options?: UseQueryOptions<TOctopusDeployScopeValues, unknown, TOctopusDeployScopeValues>
|
options?: UseQueryOptions<
|
||||||
|
TOctopusDeployVariableSetScopeValues,
|
||||||
|
unknown,
|
||||||
|
TOctopusDeployVariableSetScopeValues
|
||||||
|
>
|
||||||
) =>
|
) =>
|
||||||
useQuery({
|
useQuery({
|
||||||
queryKey: integrationAuthKeys.getIntegrationAuthOctopusDeployScopeValues(params),
|
queryKey: integrationAuthKeys.getIntegrationAuthOctopusDeployScopeValues(params),
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export type TGetIntegrationAuthOctopusDeployScopeValuesDTO = {
|
|||||||
scope: OctopusDeployScope;
|
scope: OctopusDeployScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TOctopusDeployScopeValues = {
|
export type TOctopusDeployVariableSetScopeValues = {
|
||||||
Environments: { Id: string; Name: string }[];
|
Environments: { Id: string; Name: string }[];
|
||||||
Machines: { Id: string; Name: string }[];
|
Machines: { Id: string; Name: string }[];
|
||||||
Actions: { Id: string; Name: string }[];
|
Actions: { Id: string; Name: string }[];
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { createNotification } from "@app/components/notifications";
|
|||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
|
||||||
import { workspaceKeys } from "../workspace";
|
import { workspaceKeys } from "../workspace";
|
||||||
import { TCloudIntegration, TIntegrationWithEnv } from "./types";
|
import { TCloudIntegration, TIntegrationWithEnv, TOctopusDeployScopeValues } from "./types";
|
||||||
|
|
||||||
export const integrationQueryKeys = {
|
export const integrationQueryKeys = {
|
||||||
getIntegrations: () => ["integrations"] as const,
|
getIntegrations: () => ["integrations"] as const,
|
||||||
@@ -87,14 +87,7 @@ export const useCreateIntegration = () => {
|
|||||||
shouldMaskSecrets?: boolean;
|
shouldMaskSecrets?: boolean;
|
||||||
shouldProtectSecrets?: boolean;
|
shouldProtectSecrets?: boolean;
|
||||||
shouldEnableDelete?: boolean;
|
shouldEnableDelete?: boolean;
|
||||||
octopusDeployScopeValues?: {
|
octopusDeployScopeValues?: TOctopusDeployScopeValues;
|
||||||
Environment?: string[];
|
|
||||||
Action?: string[];
|
|
||||||
Channel?: string[];
|
|
||||||
Machine?: string[];
|
|
||||||
ProcessOwner?: string[];
|
|
||||||
Role?: string[];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -57,9 +57,20 @@ export type TIntegration = {
|
|||||||
shouldMaskSecrets?: boolean;
|
shouldMaskSecrets?: boolean;
|
||||||
shouldProtectSecrets?: boolean;
|
shouldProtectSecrets?: boolean;
|
||||||
shouldEnableDelete?: boolean;
|
shouldEnableDelete?: boolean;
|
||||||
|
|
||||||
|
octopusDeployScopeValues?: TOctopusDeployScopeValues;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TOctopusDeployScopeValues = {
|
||||||
|
Environment?: string[];
|
||||||
|
Action?: string[];
|
||||||
|
Channel?: string[];
|
||||||
|
Machine?: string[];
|
||||||
|
ProcessOwner?: string[];
|
||||||
|
Role?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
export type TIntegrationWithEnv = TIntegration & {
|
export type TIntegrationWithEnv = TIntegration & {
|
||||||
environment: {
|
environment: {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export default function OctopusDeployIntegrationPage() {
|
|||||||
src="/images/integrations/Octopus Deploy.png"
|
src="/images/integrations/Octopus Deploy.png"
|
||||||
height={30}
|
height={30}
|
||||||
width={30}
|
width={30}
|
||||||
alt="Databricks logo"
|
alt="Octopus Deploy logo"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="ml-1.5">Octopus Deploy Integration</span>
|
<span className="ml-1.5">Octopus Deploy Integration</span>
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import {
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
FilterableSelect,
|
FilterableSelect,
|
||||||
FormControl,
|
FormControl,
|
||||||
Input,
|
|
||||||
Spinner
|
Spinner
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
|
import { SecretPathInput } from "@app/components/v2/SecretPathInput";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { useCreateIntegration, useGetIntegrationAuthApps } from "@app/hooks/api";
|
import { useCreateIntegration, useGetIntegrationAuthApps } from "@app/hooks/api";
|
||||||
import {
|
import {
|
||||||
@@ -63,6 +63,7 @@ export default function OctopusDeployCreateIntegrationPage() {
|
|||||||
|
|
||||||
const currentSpace = watch("targetSpace", octopusDeploySpaces?.[0]);
|
const currentSpace = watch("targetSpace", octopusDeploySpaces?.[0]);
|
||||||
const currentScope = watch("scope");
|
const currentScope = watch("scope");
|
||||||
|
const sourceEnv = watch("sourceEnvironment");
|
||||||
|
|
||||||
const { data: octopusDeployResources, isLoading: isOctopusDeployResourcesLoading } =
|
const { data: octopusDeployResources, isLoading: isOctopusDeployResourcesLoading } =
|
||||||
useGetIntegrationAuthApps(
|
useGetIntegrationAuthApps(
|
||||||
@@ -195,11 +196,11 @@ export default function OctopusDeployCreateIntegrationPage() {
|
|||||||
name="secretPath"
|
name="secretPath"
|
||||||
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||||
<FormControl isError={Boolean(error)} label="Secrets Path">
|
<FormControl isError={Boolean(error)} label="Secrets Path">
|
||||||
<Input
|
<SecretPathInput
|
||||||
className="mt-[1px] h-[2.46rem]"
|
placeholder="/"
|
||||||
|
environment={sourceEnv?.slug}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
placeholder={'Provide a path (defaults to "/")'}
|
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+12
@@ -55,6 +55,8 @@ export const IntegrationConnectionSection = ({ integration }: Props) => {
|
|||||||
return "Path";
|
return "Path";
|
||||||
case "bitbucket":
|
case "bitbucket":
|
||||||
return "Repository";
|
return "Repository";
|
||||||
|
case "octopus-deploy":
|
||||||
|
return "Project";
|
||||||
case "github":
|
case "github":
|
||||||
if (["github-env", "github-repo"].includes(integration.scope!)) {
|
if (["github-env", "github-repo"].includes(integration.scope!)) {
|
||||||
return "Repository";
|
return "Repository";
|
||||||
@@ -104,6 +106,16 @@ export const IntegrationConnectionSection = ({ integration }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (integration.integration === "octopus-deploy") {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormLabel className="text-sm font-semibold text-mineshaft-300" label="Space" />
|
||||||
|
<div className="text-sm text-mineshaft-300">{integration.targetEnvironment}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
["vercel", "netlify", "railway", "gitlab", "teamcity"].includes(integration.integration) ||
|
["vercel", "netlify", "railway", "gitlab", "teamcity"].includes(integration.integration) ||
|
||||||
(integration.integration === "github" && integration.scope === "github-env")
|
(integration.integration === "github" && integration.scope === "github-env")
|
||||||
|
|||||||
+7
-2
@@ -1,4 +1,5 @@
|
|||||||
import { TIntegrationWithEnv } from "@app/hooks/api/integrations/types";
|
import { TIntegrationWithEnv } from "@app/hooks/api/integrations/types";
|
||||||
|
import { OctopusDeployScopeValues } from "@app/views/IntegrationsPage/IntegrationDetailsPage/components/OctopusDeployScopeValues";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
integration: TIntegrationWithEnv;
|
integration: TIntegrationWithEnv;
|
||||||
@@ -26,13 +27,17 @@ const metadataMappings: Record<keyof NonNullable<TIntegrationWithEnv["metadata"]
|
|||||||
shouldDisableDelete: "AWS Secret Deletion Disabled",
|
shouldDisableDelete: "AWS Secret Deletion Disabled",
|
||||||
shouldMaskSecrets: "GitLab Secrets Masking Enabled",
|
shouldMaskSecrets: "GitLab Secrets Masking Enabled",
|
||||||
shouldProtectSecrets: "GitLab Secret Protection Enabled",
|
shouldProtectSecrets: "GitLab Secret Protection Enabled",
|
||||||
shouldEnableDelete: "GitHub Secret Deletion Enabled"
|
shouldEnableDelete: "GitHub Secret Deletion Enabled",
|
||||||
|
octopusDeployScopeValues: "Octopus Deploy Scope Values"
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const IntegrationSettingsSection = ({ integration }: Props) => {
|
export const IntegrationSettingsSection = ({ integration }: Props) => {
|
||||||
const renderValue = <K extends MetadataKey>(key: K, value: MetadataValue<K>) => {
|
const renderValue = <K extends MetadataKey>(key: K, value: MetadataValue<K>) => {
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
|
|
||||||
|
if (key === "octopusDeployScopeValues")
|
||||||
|
return <OctopusDeployScopeValues integration={integration} />;
|
||||||
|
|
||||||
// If it's a boolean, we render a generic "Yes" or "No" response.
|
// If it's a boolean, we render a generic "Yes" or "No" response.
|
||||||
if (typeof value === "boolean") {
|
if (typeof value === "boolean") {
|
||||||
return value ? "Yes" : "No";
|
return value ? "Yes" : "No";
|
||||||
@@ -49,7 +54,7 @@ export const IntegrationSettingsSection = ({ integration }: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key === "githubVisibilityRepoIds") {
|
if (key === "githubVisibilityRepoIds") {
|
||||||
return value.join(", ");
|
return (value as string[]).join(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
import { FormLabel, Spinner } from "@app/components/v2";
|
||||||
|
import { useGetIntegrationAuthOctopusDeployScopeValues } from "@app/hooks/api/integrationAuth/queries";
|
||||||
|
import {
|
||||||
|
OctopusDeployScope,
|
||||||
|
TOctopusDeployVariableSetScopeValues
|
||||||
|
} from "@app/hooks/api/integrationAuth/types";
|
||||||
|
import { TIntegration, TOctopusDeployScopeValues } from "@app/hooks/api/integrations/types";
|
||||||
|
|
||||||
|
type OctopusDeployScopeValuesProps = {
|
||||||
|
integration: TIntegration;
|
||||||
|
};
|
||||||
|
|
||||||
|
// remove plural since Octopus Deploy can decide whether they want to use singular or plural...
|
||||||
|
const modifyKey = (key: keyof TOctopusDeployVariableSetScopeValues) => {
|
||||||
|
switch (key) {
|
||||||
|
case "Processes":
|
||||||
|
return "ProcessOwner";
|
||||||
|
default:
|
||||||
|
return key.substring(0, key.length - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OctopusDeployScopeValues = ({ integration }: OctopusDeployScopeValuesProps) => {
|
||||||
|
const hasScopeValues = Boolean(
|
||||||
|
Object.values(integration.metadata?.octopusDeployScopeValues ?? {}).some(
|
||||||
|
(values) => values.length > 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: scopeValues = {}, isLoading } = useGetIntegrationAuthOctopusDeployScopeValues(
|
||||||
|
{
|
||||||
|
scope: OctopusDeployScope.Project,
|
||||||
|
spaceId: integration.targetEnvironmentId!,
|
||||||
|
resourceId: integration.appId!,
|
||||||
|
integrationAuthId: integration.integrationAuthId
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: hasScopeValues
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!integration.metadata?.octopusDeployScopeValues)
|
||||||
|
return <span className="text-sm text-mineshaft-400">Not Configured</span>;
|
||||||
|
|
||||||
|
if (isLoading) return <Spinner size="sm" className="mt-2 ml-2" />;
|
||||||
|
|
||||||
|
const scopeValuesMap = new Map(
|
||||||
|
Object.entries(scopeValues).map(([key, values]) => [
|
||||||
|
modifyKey(key as keyof TOctopusDeployVariableSetScopeValues),
|
||||||
|
new Map((values as { Name: string; Id: string }[]).map((value) => [value.Id, value.Name]))
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{Object.entries(integration.metadata.octopusDeployScopeValues).map(([key, values]) => {
|
||||||
|
if (!values.length) return null;
|
||||||
|
|
||||||
|
const getLabel = (scope: string) => {
|
||||||
|
switch (scope as keyof TOctopusDeployScopeValues) {
|
||||||
|
case "Role":
|
||||||
|
return "Target Tags";
|
||||||
|
case "Machine":
|
||||||
|
return "Targets";
|
||||||
|
case "ProcessOwner":
|
||||||
|
return "Processes";
|
||||||
|
case "Action":
|
||||||
|
return "Steps";
|
||||||
|
default:
|
||||||
|
return `${scope}s`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-4" key={key}>
|
||||||
|
<FormLabel className="text-sm font-semibold text-mineshaft-200" label={getLabel(key)} />
|
||||||
|
|
||||||
|
<div className="text-sm text-mineshaft-300">
|
||||||
|
{values
|
||||||
|
.map((value) => scopeValuesMap.get(key)?.get(value)!)
|
||||||
|
.map((name) => (
|
||||||
|
<p key={name}>{name}</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user