|
|
@@ -1,5 +1,13 @@
|
|
|
import AnimateHeight from "react-animate-height";
|
|
|
-import React, { Component, Dispatch, useMemo, useRef, useState } from "react";
|
|
|
+import React, {
|
|
|
+ Component,
|
|
|
+ Dispatch,
|
|
|
+ useContext,
|
|
|
+ useEffect,
|
|
|
+ useMemo,
|
|
|
+ useRef,
|
|
|
+ useState,
|
|
|
+} from "react";
|
|
|
import Text from "components/porter/Text";
|
|
|
import Spacer from "components/porter/Spacer";
|
|
|
import Input from "components/porter/Input";
|
|
|
@@ -24,12 +32,21 @@ import Loading from "components/Loading";
|
|
|
import { BuildpackSelection } from "components/repo-selector/BuildpackSelection";
|
|
|
import BuildpackConfigSection from "main/home/cluster-dashboard/expanded-chart/build-settings/_BuildpackConfigSection";
|
|
|
import { BuildpackStack } from "components/repo-selector/BuildpackStack";
|
|
|
+import MultiSaveButton from "components/MultiSaveButton";
|
|
|
+import api from "shared/api";
|
|
|
+import { AxiosError } from "axios";
|
|
|
type Props = {
|
|
|
appData: any;
|
|
|
setAppData: Dispatch<any>;
|
|
|
+ onTabSwitch: () => void;
|
|
|
};
|
|
|
|
|
|
-const BuildSettingsTabStack: React.FC<Props> = ({ appData, setAppData }) => {
|
|
|
+const BuildSettingsTabStack: React.FC<Props> = ({
|
|
|
+ appData,
|
|
|
+ setAppData,
|
|
|
+ onTabSwitch,
|
|
|
+}) => {
|
|
|
+ const { setCurrentError } = useContext(Context);
|
|
|
const [updated, setUpdated] = useState(null);
|
|
|
const [branch, setBranch] = useState(appData.app.git_branch);
|
|
|
const [showSettings, setShowSettings] = useState(false);
|
|
|
@@ -52,28 +69,161 @@ const BuildSettingsTabStack: React.FC<Props> = ({ appData, setAppData }) => {
|
|
|
const [buildConfig, setBuildConfig] = useState<BuildConfig>({
|
|
|
...defaultBuildConfig,
|
|
|
});
|
|
|
+ const [runningWorkflowURL, setRunningWorkflowURL] = useState("");
|
|
|
+
|
|
|
const [actionConfig, setActionConfig] = useState<ActionConfigType>({
|
|
|
...defaultActionConfig,
|
|
|
});
|
|
|
+ const [buttonStatus, setButtonStatus] = useState<
|
|
|
+ "loading" | "successful" | string
|
|
|
+ >("");
|
|
|
|
|
|
const [imageUrl, setImageUrl] = useState(appData.chart.image_uri);
|
|
|
|
|
|
- const buildpackConfigRef = useRef<{
|
|
|
- isLoading: boolean;
|
|
|
- getBuildConfig: () => BuildConfig;
|
|
|
- }>(null);
|
|
|
+ const clearButtonStatus = (time: number = 800) => {
|
|
|
+ setTimeout(() => {
|
|
|
+ setButtonStatus("");
|
|
|
+ }, time);
|
|
|
+ };
|
|
|
+ const triggerWorkflow = async () => {
|
|
|
+ try {
|
|
|
+ await api.reRunGHWorkflow(
|
|
|
+ "",
|
|
|
+ {},
|
|
|
+ {
|
|
|
+ project_id: appData.app.project_id,
|
|
|
+ cluster_id: appData.app.cluster_id,
|
|
|
+ git_installation_id: appData.app.git_repo_id,
|
|
|
+ owner: appData.app.repo_name?.split("/")[0],
|
|
|
+ name: appData.app.repo_name?.split("/")[1],
|
|
|
+ branch: branch,
|
|
|
+ release_name: "stack_" + appData.chart.name,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ } catch (error) {
|
|
|
+ if (!error?.response) {
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+
|
|
|
+ let tmpError: AxiosError = error;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @smell
|
|
|
+ * Currently the expanded chart is clearing all the state when a chart update is triggered (saveEnvVariables).
|
|
|
+ * Temporary usage of setCurrentError until a context is applied to keep the state of the ReRunError during re renders.
|
|
|
+ */
|
|
|
+
|
|
|
+ if (tmpError.response.status === 400) {
|
|
|
+ // setReRunError({
|
|
|
+ // title: "No previous run found",
|
|
|
+ // description:
|
|
|
+ // "There are no previous runs for this workflow, please trigger manually a run before changing the build settings.",
|
|
|
+ // });
|
|
|
+ setCurrentError(
|
|
|
+ "There are no previous runs for this workflow. Please manually trigger a run before changing build settings."
|
|
|
+ );
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tmpError.response.status === 409) {
|
|
|
+ // setReRunError({
|
|
|
+ // title: "The workflow is still running",
|
|
|
+ // description:
|
|
|
+ // 'If you want to make more changes, please choose the option "Save" until the workflow finishes.',
|
|
|
+ // });
|
|
|
|
|
|
- const currentActionConfig = useMemo(() => {
|
|
|
- console.log(appData.chart.config);
|
|
|
+ if (typeof tmpError.response.data === "string") {
|
|
|
+ setRunningWorkflowURL(tmpError.response.data);
|
|
|
+ }
|
|
|
+ setCurrentError(
|
|
|
+ 'The workflow is still running. You can "Save" the current build settings for the next workflow run and view the current status of the workflow here: ' +
|
|
|
+ tmpError.response.data
|
|
|
+ );
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tmpError.response.status === 404) {
|
|
|
+ let description = "No action file matching this deployment was found.";
|
|
|
+ if (typeof tmpError.response.data === "string") {
|
|
|
+ const filename = tmpError.response.data;
|
|
|
+ description = description.concat(
|
|
|
+ `Please check that the file "${filename}" exists in your repository.`
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // setReRunError({
|
|
|
+ // title: "The action doesn't seem to exist",
|
|
|
+ // description,
|
|
|
+ // });
|
|
|
+
|
|
|
+ setCurrentError(description);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const saveConfig = async () => {
|
|
|
console.log(appData);
|
|
|
- const actionConf = appData.chart.config;
|
|
|
+ try {
|
|
|
+ await api.updatePorterApp(
|
|
|
+ "<token>",
|
|
|
+ {
|
|
|
+ repo_name: appData.app.repo_name,
|
|
|
+ git_branch: branch,
|
|
|
+ build_context: appData.app.build_context,
|
|
|
+ builder: buildConfig.builder,
|
|
|
+ buildpacks: buildConfig.buildpacks?.join(","),
|
|
|
+ dockerfile: appData.app.dockerfile,
|
|
|
+ image_repo_uri: appData.chart.image_repo_uri,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ project_id: appData.app.project_id,
|
|
|
+ cluster_id: appData.app.cluster_id,
|
|
|
+ name: appData.app.name,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ onTabSwitch();
|
|
|
+ } catch (err) {
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const handleSave = async () => {
|
|
|
+ setButtonStatus("loading");
|
|
|
+
|
|
|
+ try {
|
|
|
+ console.log(buildConfig.builder);
|
|
|
|
|
|
- return {
|
|
|
- kind: "github",
|
|
|
- ...actionConf,
|
|
|
- } as FullActionConfigType;
|
|
|
- }, [appData.chart]);
|
|
|
+ await saveConfig();
|
|
|
+ setAppData(appData);
|
|
|
|
|
|
+ onTabSwitch();
|
|
|
+ setButtonStatus("successful");
|
|
|
+ } catch (error) {
|
|
|
+ setButtonStatus("Something went wrong");
|
|
|
+ console.log(error);
|
|
|
+ } finally {
|
|
|
+ clearButtonStatus();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const handleSaveAndReDeploy = async () => {
|
|
|
+ setButtonStatus("loading");
|
|
|
+
|
|
|
+ try {
|
|
|
+ console.log(buildConfig.builder);
|
|
|
+
|
|
|
+ await saveConfig();
|
|
|
+ setAppData(appData);
|
|
|
+
|
|
|
+ await triggerWorkflow();
|
|
|
+
|
|
|
+ onTabSwitch();
|
|
|
+ setButtonStatus("successful");
|
|
|
+ } catch (error) {
|
|
|
+ setButtonStatus("Something went wrong");
|
|
|
+ console.log(error);
|
|
|
+ } finally {
|
|
|
+ clearButtonStatus();
|
|
|
+ }
|
|
|
+ };
|
|
|
return (
|
|
|
<>
|
|
|
<Text size={16}>Build settings</Text>
|
|
|
@@ -145,10 +295,35 @@ const BuildSettingsTabStack: React.FC<Props> = ({ appData, setAppData }) => {
|
|
|
}}
|
|
|
hide={!showSettings}
|
|
|
currentBuildConfig={buildConfig}
|
|
|
+ setBuildConfig={setBuildConfig}
|
|
|
/>
|
|
|
)}
|
|
|
</StyledSourceBox>
|
|
|
</AnimateHeight>
|
|
|
+
|
|
|
+ <MultiSaveButton
|
|
|
+ options={[
|
|
|
+ {
|
|
|
+ text: "Save",
|
|
|
+ onClick: handleSave,
|
|
|
+ description:
|
|
|
+ "Save the build settings to be used in the next workflow run",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: "Save and Redeploy",
|
|
|
+ onClick: handleSaveAndReDeploy,
|
|
|
+ description:
|
|
|
+ "Immediately trigger a workflow run with updated build settings",
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ disabled={false}
|
|
|
+ makeFlush={true}
|
|
|
+ clearPosition={true}
|
|
|
+ statusPosition="left"
|
|
|
+ expandTo="left"
|
|
|
+ saveText=""
|
|
|
+ status={buttonStatus}
|
|
|
+ ></MultiSaveButton>
|
|
|
</>
|
|
|
);
|
|
|
};
|
|
|
@@ -162,19 +337,6 @@ const DarkMatter = styled.div<{ antiHeight?: string }>`
|
|
|
margin-top: ${(props) => props.antiHeight || "-15px"};
|
|
|
`;
|
|
|
|
|
|
-const Subtitle = styled.div`
|
|
|
- padding: 11px 0px 16px;
|
|
|
- font-family: "Work Sans", sans-serif;
|
|
|
- font-size: 13px;
|
|
|
- color: #aaaabb;
|
|
|
- line-height: 1.6em;
|
|
|
-`;
|
|
|
-
|
|
|
-const Required = styled.div`
|
|
|
- margin-left: 8px;
|
|
|
- color: #fc4976;
|
|
|
- display: inline-block;
|
|
|
-`;
|
|
|
const AdvancedBuildTitle = styled.div`
|
|
|
display: flex;
|
|
|
align-items: center;
|