1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-31 19:35:21 +02:00

feat(helm): show manifest previews/changes when installing and upgrading a helm chart [r8s-405] (#898)

This commit is contained in:
Ali 2025-07-23 10:52:58 +12:00 committed by GitHub
parent a4cff13531
commit 60bc04bc33
41 changed files with 763 additions and 157 deletions

View file

@ -1,9 +1,10 @@
import { useState } from 'react';
import { useMemo, useState } from 'react';
import { ArrowUp } from 'lucide-react';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { ChartVersion } from '@/react/kubernetes/helm/queries/useHelmRepoVersions';
import { ChartVersion } from '@/react/kubernetes/helm/helmChartSourceQueries/useHelmRepoVersions';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { Modal, OnSubmit, openModal } from '@@/modals';
import { Button } from '@@/buttons';
@ -15,26 +16,32 @@ import { Option, PortainerSelect } from '@@/form-components/PortainerSelect';
import { UpdateHelmReleasePayload } from '../../types';
import { HelmValuesInput } from '../../components/HelmValuesInput';
import { useHelmChartValues } from '../../queries/useHelmChartValues';
import { useHelmChartValues } from '../../helmChartSourceQueries/useHelmChartValues';
import { ManifestPreviewFormSection } from '../../components/ManifestPreviewFormSection';
interface Props {
onSubmit: OnSubmit<UpdateHelmReleasePayload>;
payload: UpdateHelmReleasePayload;
helmReleaseInitialValues: UpdateHelmReleasePayload;
releaseManifest: string;
versions: ChartVersion[];
chartName: string;
environmentId: EnvironmentId;
}
export function UpgradeHelmModal({
payload,
helmReleaseInitialValues,
releaseManifest,
versions,
onSubmit,
chartName,
environmentId,
}: Props) {
const versionOptions: Option<ChartVersion>[] = versions.map((version) => {
const repo = payload.repo === version.Repo ? version.Repo : '';
const repo =
helmReleaseInitialValues.repo === version.Repo ? version.Repo : '';
const isCurrentVersion =
version.AppVersion === payload.appVersion &&
version.Version === payload.version;
version.AppVersion === helmReleaseInitialValues.appVersion &&
version.Version === helmReleaseInitialValues.version;
const label = `${repo}@${version.Version}${
isCurrentVersion ? ' (current)' : ''
@ -50,13 +57,16 @@ export function UpgradeHelmModal({
const defaultVersion =
versionOptions.find(
(v) =>
v.value.AppVersion === payload.appVersion &&
v.value.Version === payload.version &&
v.value.Repo === payload.repo
v.value.AppVersion === helmReleaseInitialValues.appVersion &&
v.value.Version === helmReleaseInitialValues.version &&
v.value.Repo === helmReleaseInitialValues.repo
)?.value || versionOptions[0]?.value;
const [version, setVersion] = useState<ChartVersion>(defaultVersion);
const [userValues, setUserValues] = useState<string>(payload.values || '');
const [userValues, setUserValues] = useState<string>(
helmReleaseInitialValues.values || ''
);
const [atomic, setAtomic] = useState<boolean>(true);
const [previewIsValid, setPreviewIsValid] = useState<boolean>(false);
const chartValuesRefQuery = useHelmChartValues({
chart: chartName,
@ -64,6 +74,19 @@ export function UpgradeHelmModal({
version: version.Version,
});
const submitPayload = useMemo(
() => ({
name: helmReleaseInitialValues.name,
values: userValues,
namespace: helmReleaseInitialValues.namespace,
chart: helmReleaseInitialValues.chart,
repo: version.Repo,
version: version.Version,
atomic,
}),
[helmReleaseInitialValues, userValues, version, atomic]
);
return (
<Modal
onDismiss={() => onSubmit()}
@ -84,7 +107,7 @@ export function UpgradeHelmModal({
>
<Input
id="release-name-input"
value={payload.name}
value={helmReleaseInitialValues.name}
readOnly
disabled
data-cy="helm-release-name-input"
@ -97,7 +120,7 @@ export function UpgradeHelmModal({
>
<Input
id="namespace-input"
value={payload.namespace}
value={helmReleaseInitialValues.namespace}
readOnly
disabled
data-cy="helm-namespace-input"
@ -134,6 +157,15 @@ export function UpgradeHelmModal({
valuesRef={chartValuesRefQuery.data?.values ?? ''}
isValuesRefLoading={chartValuesRefQuery.isInitialLoading}
/>
<div className="mb-10">
<ManifestPreviewFormSection
payload={submitPayload}
onChangePreviewValidation={setPreviewIsValid}
title="Manifest changes"
currentManifest={releaseManifest}
environmentId={environmentId}
/>
</div>
</div>
</Modal.Body>
</div>
@ -149,17 +181,8 @@ export function UpgradeHelmModal({
Cancel
</Button>
<Button
onClick={() =>
onSubmit({
name: payload.name,
values: userValues,
namespace: payload.namespace,
chart: payload.chart,
repo: version.Repo,
version: version.Version,
atomic,
})
}
onClick={() => onSubmit(submitPayload)}
disabled={!previewIsValid}
color="primary"
key="update-button"
size="medium"
@ -174,12 +197,16 @@ export function UpgradeHelmModal({
}
export async function openUpgradeHelmModal(
payload: UpdateHelmReleasePayload,
versions: ChartVersion[]
helmReleaseInitialValues: UpdateHelmReleasePayload,
versions: ChartVersion[],
releaseManifest: string,
environmentId: EnvironmentId
) {
return openModal(withReactQuery(withCurrentUser(UpgradeHelmModal)), {
payload,
helmReleaseInitialValues,
versions,
chartName: payload.chart,
chartName: helmReleaseInitialValues.chart,
releaseManifest,
environmentId,
});
}