diff --git a/ui/src/app/shared/artifacts.ts b/ui/src/app/shared/artifacts.ts
index 12349448447e..f27746eac5de 100644
--- a/ui/src/app/shared/artifacts.ts
+++ b/ui/src/app/shared/artifacts.ts
@@ -41,6 +41,24 @@ export const artifactURN = (a: A, ar: ArtifactRepository) =>
return 'artifact:unknown';
};
+export const artifactRepoHasLocation = (ar: ArtifactRepository) => {
+ if (ar.gcs) {
+ return ar.gcs.bucket !== '' && ar.gcs.key !== '';
+ } else if (ar.git) {
+ return ar.git.repo !== '';
+ } else if (ar.http) {
+ return ar.http.url !== '';
+ } else if (ar.s3) {
+ return ar.s3.endpoint !== '' && ar.s3.bucket !== '' && ar.s3.key !== '';
+ } else if (ar.oss) {
+ return ar.oss.bucket !== '' && ar.oss.endpoint !== '' && ar.oss.key !== '';
+ } else if (ar.raw) {
+ return true;
+ } else if (ar.azure) {
+ return ar.azure.container !== '' && ar.azure.blob !== '';
+ }
+};
+
export const artifactKey = (a: A) => {
if (a.gcs) {
return a.gcs.key;
diff --git a/ui/src/app/workflows/components/workflow-details/workflow-details.tsx b/ui/src/app/workflows/components/workflow-details/workflow-details.tsx
index fab2c6af24b7..90da893d8baa 100644
--- a/ui/src/app/workflows/components/workflow-details/workflow-details.tsx
+++ b/ui/src/app/workflows/components/workflow-details/workflow-details.tsx
@@ -3,9 +3,9 @@ import * as classNames from 'classnames';
import * as React from 'react';
import {useContext, useEffect, useRef, useState} from 'react';
import {RouteComponentProps} from 'react-router';
-import {execSpec, Link, NodeStatus, Parameter, Workflow} from '../../../../models';
+import {ArtifactRepository, execSpec, Link, NodeStatus, Parameter, Workflow} from '../../../../models';
import {ANNOTATION_KEY_POD_NAME_VERSION} from '../../../shared/annotations';
-import {findArtifact} from '../../../shared/artifacts';
+import {artifactRepoHasLocation, findArtifact} from '../../../shared/artifacts';
import {uiUrl} from '../../../shared/base';
import {CostOptimisationNudge} from '../../../shared/components/cost-optimisation-nudge';
import {ErrorNotice} from '../../../shared/components/error-notice';
@@ -18,6 +18,7 @@ import {historyUrl} from '../../../shared/history';
import {getPodName, getTemplateNameFromNode} from '../../../shared/pod-name';
import {RetryWatch} from '../../../shared/retry-watch';
import {services} from '../../../shared/services';
+import {getResolvedTemplates} from '../../../shared/template-resolution';
import {useQueryParams} from '../../../shared/use-query-params';
import {useResizableWidth} from '../../../shared/use-resizable-width';
import {useTransition} from '../../../shared/use-transition';
@@ -68,6 +69,7 @@ export const WorkflowDetails = ({history, location, match}: RouteComponentProps<
const [error, setError] = useState();
const selectedNode = workflow && workflow.status && workflow.status.nodes && workflow.status.nodes[nodeId];
const selectedArtifact = workflow && workflow.status && findArtifact(workflow.status, nodeId);
+ const [selectedTemplateArtifactRepo, setSelectedTemplateArtifactRepo] = useState();
const isSidePanelExpanded = !!(selectedNode || selectedArtifact);
const isSidePanelAnimating = useTransition(isSidePanelExpanded, ANIMATION_MS + ANIMATION_BUFFER_MS);
const {width: sidePanelWidth, dragHandleProps: sidePanelDragHandleProps} = useResizableWidth({
@@ -101,6 +103,22 @@ export const WorkflowDetails = ({history, location, match}: RouteComponentProps<
);
};
+ useEffect(() => {
+ // update the default Artifact Repository for the Template that corresponds to the selectedArtifact
+ // if there's an ArtifactLocation configured for the Template we use that
+ // otherwise we use the central one for the Workflow configured in workflow.status.artifactRepositoryRef.artifactRepository
+ // (Note that individual Artifacts may also override whatever this gets set to)
+ if (workflow && workflow.status && workflow.status.nodes && selectedArtifact) {
+ const template = getResolvedTemplates(workflow, workflow.status.nodes[selectedArtifact.nodeId]);
+ const artifactRepo = template.archiveLocation;
+ if (artifactRepo && artifactRepoHasLocation(artifactRepo)) {
+ setSelectedTemplateArtifactRepo(artifactRepo);
+ } else {
+ setSelectedTemplateArtifactRepo(workflow.status.artifactRepositoryRef.artifactRepository);
+ }
+ }
+ }, [workflow, selectedArtifact]);
+
useEffect(() => {
history.push(historyUrl('workflows/{namespace}/{name}', {namespace, name, tab, nodeId, nodePanelView, sidePanel}));
}, [namespace, name, tab, nodeId, nodePanelView, sidePanel]);
@@ -450,9 +468,7 @@ export const WorkflowDetails = ({history, location, match}: RouteComponentProps<
onResume={() => renderResumePopup()}
/>
)}
- {selectedArtifact && (
-
- )}
+ {selectedArtifact && }
))}
diff --git a/ui/src/models/workflows.ts b/ui/src/models/workflows.ts
index 83bc16b30b2e..7c3d42f4a722 100644
--- a/ui/src/models/workflows.ts
+++ b/ui/src/models/workflows.ts
@@ -27,19 +27,37 @@ export interface Arguments {
export interface AzureArtifactRepository {
endpoint: string;
container: string;
+ blob: string;
}
export interface GCSArtifactRepository {
endpoint: string;
bucket: string;
+ key: string;
}
export interface S3ArtifactRepository {
endpoint: string;
bucket: string;
+ key: string;
}
export interface OSSArtifactRepository {
endpoint: string;
bucket: string;
+ key: string;
+}
+
+export interface GitArtifactRepository {
+ repo?: string;
+ endpoint?: string;
+ bucket?: string;
+}
+
+export interface HTTPArtifactRepository {
+ url: string;
+}
+
+export interface RawArtifactRepository {
+ data: string;
}
export interface ArtifactRepository {
@@ -47,6 +65,9 @@ export interface ArtifactRepository {
s3?: S3ArtifactRepository;
oss?: OSSArtifactRepository;
azure?: AzureArtifactRepository;
+ git?: GitArtifactRepository;
+ http?: HTTPArtifactRepository;
+ raw?: RawArtifactRepository;
}
export interface ArtifactRepositoryRefStatus {
artifactRepository: ArtifactRepository;
@@ -440,6 +461,11 @@ export interface Template {
* Sidecars is a list of containers which run alongside the main container Sidecars are automatically killed when the main container completes
*/
sidecars?: UserContainer[];
+ /**
+ * archiveLocation is the location in which all files related to the step will be stored (logs, artifacts, etc...).
+ * Can be overridden by individual items in outputs. If omitted, will use the default
+ */
+ archiveLocation?: ArtifactRepository;
/**
* InitContainers is a list of containers which run before the main container.
*/