Repository: argoproj/argo (go)

Issue:
v2.9.5 brew binary somehow getting replaced by dirty
## Summary 

`brew install argo` should give me a working binary - but the one I actually get does not have the static files.

## Diagnostics

From brew:

```
argo: v2.9.5+5759a0e.dirty
  BuildDate: 2020-08-07T21:09:01Z
  GitCommit: 5759a0e198d333fa8c3e0aeee433d93808c0dc72
  GitTreeState: dirty
  GitTag: v2.9.5
  GoVersion: go1.14.6
  Compiler: gc
  Platform: darwin/amd64
```

From releases page:

```
argo: v2.9.5
  BuildDate: 2020-08-06T22:13:32Z
  GitCommit: 5759a0e198d333fa8c3e0aeee433d93808c0dc72
  GitTreeState: clean
  GitTag: v2.9.5
  GoVersion: go1.13
  Compiler: gc
  Platform: darwin/amd64
```
---
<!-- Issue Author: Don't delete this message to encourage other users to support your issue! -->
**Message from the maintainers**:

Impacted by this bug? Give it a 👍. We prioritise the issues with the most 👍.


Pull request description:
ci: static files not being built with Homebrew and dirty binary. Fixes #3769
This should fix the problems with the `homebrew-core` build as proposed by @alexec in https://github.com/argoproj/argo/issues/3769

Checklist:

* [x] Either (a) I've created an [enhancement proposal](https://github.com/argoproj/argo/issues/new/choose) and discussed it with the community, (b) this is a bug fix, or (c) this is a chore.
* [x] The title of the PR is (a) [conventional](https://www.conventionalcommits.org/en/v1.0.0/), (b) states what changed, and (c) suffixes the related issues number. E.g. `"fix(controller): Updates such and such. Fixes #1234"`.  
* [x] I've signed the CLA.
* [x] I have written unit and/or e2e tests for my change. PRs without these are unlikely to be merged.
* [ ] My builds are green. Try syncing with master if they are not. 
* [ ] My organization is added to [USERS.md](https://github.com/argoproj/argo/blob/master/USERS.md).


Patch:
diff --git a/.dockerignore b/.dockerignore
index c434b1e7b..5a5fbf33d 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,4 +1,4 @@
-# Prevent vendor directory from being copied to ensure we are not not pulling unexpected cruft from 
+# Prevent vendor directory from being copied to ensure we are not not pulling unexpected cruft from
 # a user's workspace, and are only building off of what is locked by dep.
 .idea
 assets
@@ -8,3 +8,4 @@ sdks
 vendor
 ui/dist
 ui/node_modules
+Dockerfile
\ No newline at end of file
diff --git a/.github/workflows/ci-build.yaml b/.github/workflows/ci-build.yaml
index a9e55e17b..e22b5bb54 100644
--- a/.github/workflows/ci-build.yaml
+++ b/.github/workflows/ci-build.yaml
@@ -1,8 +1,8 @@
 name: CI
-on: 
+on:
   push:
     branches:
-      - 'master' 
+      - 'master'
       - 'release-*'
       - '!release-2.8'
   pull_request:
@@ -56,6 +56,7 @@ jobs:
         env:
           GOPATH: /home/runner/go
           PROFILE: mysql
+          STATIC_FILES: false
         run: |
           echo '127.0.0.1 dex'      | sudo tee -a /etc/hosts
           echo '127.0.0.1 minio'    | sudo tee -a /etc/hosts
diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml
index aa8cc1ae2..1d07d3ae9 100644
--- a/.github/workflows/docker-image.yml
+++ b/.github/workflows/docker-image.yml
@@ -17,6 +17,13 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
+      # https://github.com/marketplace/actions/docker-buildx
+      - name: Set up Docker Buildx
+        id: buildx
+        uses: crazy-max/ghaction-docker-buildx@v3
+        with:
+          buildx-version: latest
+          qemu-version: latest
       - name: Docker Login
         uses: Azure/docker-login@v1
         with:
@@ -25,19 +32,19 @@ jobs:
       - name: Build & Push Linux Docker Images
         env:
           DOCKERIO_ORG: ${{ secrets.DOCKERIO_ORG }}
+        # https://github.com/marketplace/actions/docker-buildx#build-and-push-to-dockerhub
         run: |
-          docker_org=$DOCKERIO_ORG
-
           tag=$(basename $GITHUB_REF)
           if [ $tag = "master" ]; then
             tag="latest"
           fi
-
           targets="workflow-controller argoexec argocli"
           for target in $targets; do
-            image_name="${docker_org}/${target}:${tag}-linux"
-            docker build --target $target -t $image_name .
-            docker push $image_name
+            docker buildx build \
+              --output "type=image,push=true" \
+              --platform="linux/amd64,linux/arm64,linux/ppc64le,linux/s390x" \
+              --target $target \
+              --tag "${DOCKERIO_ORG}/${target}:${tag}-linux" .
           done
 
   build-windows:
diff --git a/.gitignore b/.gitignore
index 022d165ce..1b95c1db3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,4 @@ git-ask-pass.sh
 /pkg/apiclient/workflowtemplate/workflow-template.swagger.json
 /site/
 /node_modules/
+/.brew_home
diff --git a/Dockerfile b/Dockerfile
index 4121221c9..151b3fb09 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,7 +6,6 @@
 FROM golang:1.13.4 as builder
 
 ARG IMAGE_OS=linux
-ARG IMAGE_ARCH=amd64
 
 RUN apt-get update && apt-get --no-install-recommends install -y \
     git \
@@ -32,10 +31,13 @@ WORKDIR /tmp
 ENV DOCKER_CHANNEL stable
 ENV DOCKER_VERSION 18.09.1
 
-RUN if [ "${IMAGE_OS}" = "linux" -a "${IMAGE_ARCH}" = "amd64" ]; then \
-    	wget -O docker.tgz https://download.docker.com/linux/static/${DOCKER_CHANNEL}/x86_64/docker-${DOCKER_VERSION}.tgz; \
-    elif [ "${IMAGE_OS}" = "linux" -a "${IMAGE_ARCH}" = "arm64" ]; then \
-	wget -O docker.tgz https://download.docker.com/linux/static/${DOCKER_CHANNEL}/aarch64/docker-${DOCKER_VERSION}.tgz; \
+RUN if [ "${IMAGE_OS}" = "linux" ]; then \
+        export IMAGE_ARCH=`uname -m`; \
+        if [ "${IMAGE_ARCH}" = "ppc64le" ] ||[ "${IMAGE_ARCH}" = "s390x" ]; then \
+	        wget -O docker.tgz https://download.docker.com/linux/static/${DOCKER_CHANNEL}/${IMAGE_ARCH}/docker-18.06.3-ce.tgz; \
+        else \
+            wget -O docker.tgz https://download.docker.com/linux/static/${DOCKER_CHANNEL}/${IMAGE_ARCH}/docker-${DOCKER_VERSION}.tgz; \
+        fi \
     fi && \
     tar --extract --file docker.tgz --strip-components 1 --directory /usr/local/bin/ && \
     rm docker.tgz
@@ -47,7 +49,6 @@ RUN if [ "${IMAGE_OS}" = "linux" -a "${IMAGE_ARCH}" = "amd64" ]; then \
 FROM debian:10.3-slim as argoexec-base
 
 ARG IMAGE_OS=linux
-ARG IMAGE_ARCH=amd64
 
 # NOTE: keep the version synced with https://storage.googleapis.com/kubernetes-release/release/stable.txt
 ENV KUBECTL_VERSION=1.15.1
@@ -62,10 +63,12 @@ RUN apt-get update && \
         /usr/share/man \
         /usr/share/doc \
         /usr/share/doc-base
-ADD hack/recurl.sh .
-RUN ./recurl.sh /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/${IMAGE_ARCH}/kubectl
+
+ADD hack/recurl.sh hack/image_arch.sh .
+RUN . ./image_arch.sh && ./recurl.sh /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/${IMAGE_ARCH}/kubectl
 RUN ./recurl.sh /usr/local/bin/jq https://github.com/stedolan/jq/releases/download/jq-${JQ_VERSION}/jq-linux64
 RUN rm recurl.sh
+
 COPY hack/ssh_known_hosts /etc/ssh/ssh_known_hosts
 COPY --from=builder /usr/local/bin/docker /usr/local/bin/
 
@@ -76,7 +79,7 @@ FROM node:14.0.0 as argo-ui
 ADD ["ui", "ui"]
 ADD ["api", "api"]
 
-RUN yarn --cwd ui install
+RUN yarn --cwd ui install --network-timeout 1000000
 RUN yarn --cwd ui build
 
 ####################################################################################################
@@ -85,7 +88,6 @@ RUN yarn --cwd ui build
 FROM builder as argo-build
 
 ARG IMAGE_OS=linux
-ARG IMAGE_ARCH=amd64
 
 # Perform the build
 WORKDIR /go/src/github.com/argoproj/argo
@@ -93,13 +95,14 @@ COPY . .
 # check we can use Git
 RUN git rev-parse HEAD
 
+ADD hack/image_arch.sh .
 # controller image
-RUN make dist/workflow-controller-linux-${IMAGE_ARCH}
-RUN ["sh", "-c", "./dist/workflow-controller-linux-${IMAGE_ARCH} version | grep clean"]
+RUN . ./image_arch.sh && make dist/workflow-controller-linux-${IMAGE_ARCH}
+RUN . ./image_arch.sh && ./dist/workflow-controller-linux-${IMAGE_ARCH} version | grep clean
 
 # executor image
-RUN make dist/argoexec-linux-${IMAGE_ARCH}
-RUN ["sh", "-c", "./dist/argoexec-linux-${IMAGE_ARCH} version | grep clean"]
+RUN . ./image_arch.sh && make dist/argoexec-linux-${IMAGE_ARCH}
+RUN . ./image_arch.sh && ./dist/argoexec-linux-${IMAGE_ARCH} version | grep clean
 
 # cli image
 RUN mkdir -p ui/dist
@@ -107,8 +110,8 @@ COPY --from=argo-ui ui/dist/app ui/dist/app
 # stop make from trying to re-build this without yarn installed
 RUN touch ui/dist/node_modules.marker
 RUN touch ui/dist/app/index.html
-RUN make argo-server.crt argo-server.key dist/argo-linux-${IMAGE_ARCH}
-RUN ["sh", "-c", "./dist/argo-linux-${IMAGE_ARCH} version | grep clean"]
+RUN . ./image_arch.sh && make argo-server.crt argo-server.key dist/argo-linux-${IMAGE_ARCH}
+RUN . ./image_arch.sh && ./dist/argo-linux-${IMAGE_ARCH} version | grep clean
 
 ####################################################################################################
 # argoexec
diff --git a/Makefile b/Makefile
index c20d04709..6d8ed7963 100644
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ CONTROLLER_IMAGE_FILE  := dist/controller-image.marker
 
 # perform static compilation
 STATIC_BUILD          ?= true
-CI                    ?= false
+STATIC_FILES          ?= true
 PROFILE               ?= minimal
 # whether or not to start the Argo Service in TLS mode
 SECURE                := false
@@ -51,7 +51,7 @@ AUTH_MODE             := hybrid
 ifeq ($(PROFILE),sso)
 AUTH_MODE             := sso
 endif
-ifeq ($(CI),true)
+ifeq ($(STATIC_FILES),false)
 AUTH_MODE             := client
 endif
 K3D                   := $(shell if [ "`which kubectl`" != '' ] && [ "`kubectl config current-context`" = "k3s-default" ]; then echo true; else echo false; fi)
@@ -66,7 +66,7 @@ ifeq ($(PROFILE),postgres)
 ALWAYS_OFFLOAD_NODE_STATUS := true
 endif
 
-ifeq ($(CI),true)
+ifeq ($(STATIC_FILES),false)
 TEST_OPTS := -coverprofile=coverage.out
 else
 TEST_OPTS :=
@@ -140,7 +140,7 @@ cli: dist/argo argo-server.crt argo-server.key
 ui/dist/node_modules.marker: ui/package.json ui/yarn.lock
 	# Get UI dependencies
 	@mkdir -p ui/node_modules
-ifeq ($(CI),false)
+ifeq ($(STATIC_FILES),true)
 	yarn --cwd ui install
 endif
 	@mkdir -p ui/dist
@@ -149,7 +149,7 @@ endif
 ui/dist/app/index.html: ui/dist/node_modules.marker $(UI_FILES)
 	# Build UI
 	@mkdir -p ui/dist/app
-ifeq ($(CI),false)
+ifeq ($(STATIC_FILES),true)
 	yarn --cwd ui build
 else
 	echo "Built without static files" > ui/dist/app/index.html
@@ -198,6 +198,8 @@ controller: dist/workflow-controller
 dist/workflow-controller: GOARGS = GOOS= GOARCH=
 dist/workflow-controller-linux-amd64: GOARGS = GOOS=linux GOARCH=amd64
 dist/workflow-controller-linux-arm64: GOARGS = GOOS=linux GOARCH=arm64
+dist/workflow-controller-linux-ppc64le: GOARGS = GOOS=linux GOARCH=ppc64le
+dist/workflow-controller-linux-s390x: GOARGS = GOOS=linux GOARCH=s390x
 
 dist/workflow-controller: $(CONTROLLER_PKGS)
 	go build -v -i -ldflags '${LDFLAGS}' -o $@ ./cmd/workflow-controller
@@ -216,6 +218,8 @@ $(CONTROLLER_IMAGE_FILE): $(CONTROLLER_PKGS)
 dist/argoexec-linux-amd64: GOARGS = GOOS=linux GOARCH=amd64
 dist/argoexec-windows-amd64: GOARGS = GOOS=windows GOARCH=amd64
 dist/argoexec-linux-arm64: GOARGS = GOOS=linux GOARCH=arm64
+dist/argoexec-linux-ppc64le: GOARGS = GOOS=linux GOARCH=ppc64le
+dist/argoexec-linux-s390x: GOARGS = GOOS=linux GOARCH=s390x
 
 dist/argoexec-%: $(ARGOEXEC_PKGS)
 	CGO_ENABLED=0 $(GOARGS) go build -v -i -ldflags '${LDFLAGS}' -o $@ ./cmd/argoexec
@@ -310,7 +314,7 @@ lint: server/static/files.go $(GOPATH)/bin/golangci-lint
 	# Lint Go files
 	golangci-lint run --fix --verbose --concurrency 4 --timeout 5m
 	# Lint UI files
-ifeq ($(CI),false)
+ifeq ($(STATIC_FILES),true)
 	yarn --cwd ui lint
 endif
 
diff --git a/USERS.md b/USERS.md
index 50d21033c..b7ef8afbc 100644
--- a/USERS.md
+++ b/USERS.md
@@ -54,6 +54,7 @@ Currently, the following organizations are **officially** using Argo Workflows:
 1. [Max Kelsen](https://maxkelsen.com/)
 1. [Microba](https://www.microba.com/)
 1. [Mirantis](https://mirantis.com/)
+1. [New Relic](https://newrelic.com/)
 1. [NVIDIA](https://www.nvidia.com/)
 1. [OVH](https://www.ovh.com/)
 1. [Peak AI](https://www.peak.ai/)
diff --git a/docs/access-token.md b/docs/access-token.md
index 583d83d24..3d72b4103 100644
--- a/docs/access-token.md
+++ b/docs/access-token.md
@@ -26,8 +26,8 @@ kubectl create rolebinding jenkins --role=jenkins --serviceaccount=argo:jenkins
 You now need to get a token:
 
 ```sh
-SECRET=$(kubectl -n argo get sa jenkins -o=jsonpath='{.secrets[0].name}')
-ARGO_TOKEN="Bearer $(kubectl -n argo get secret $SECRET -o=jsonpath='{.data.token}' | base64 --decode)"
+SECRET=$(kubectl get sa jenkins -o=jsonpath='{.secrets[0].name}')
+ARGO_TOKEN="Bearer $(kubectl get secret $SECRET -o=jsonpath='{.data.token}' | base64 --decode)"
 echo $ARGO_TOKEN
 Bearer ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNkltS...
 ```
diff --git a/docs/cron-workflows.md b/docs/cron-workflows.md
index d693b98df..a3eff667c 100644
--- a/docs/cron-workflows.md
+++ b/docs/cron-workflows.md
@@ -51,6 +51,16 @@ The resuling `Workflow` name will be a generated name based on the `CronWorkflow
 | `successfulJobsHistoryLimit` |           `3`          | Number of successful `Workflows` that will be persisted at a time                                                                                                                                                                      |
 | `failedJobsHistoryLimit`     | `1`                    | Number of failed `Workflows` that will be persisted at a time                                                                                                                                                                          |
 
+### Crash Recovery
+
+If the `workflow-controller` crashes (and hence the `CronWorkflow` controller), there are some options you can set to ensure that `CronWorkflows` that would have been scheduled while the controller was down can still run. Mainly `startingDeadlineSeconds` can be set to specify the maximum number of seconds past the last successful run of a `CronWorkflow` during which a missed run will still be executed.
+
+For example, if a `CronWorkflow` that runs every minute is last run at 12:05:00, and the controller crashes between 12:05:55 and 12:06:05, then the expected execution time of 12:06:00 would be missed. However, if `startingDeadlineSeconds` is set to a value greater than 65 (the amount of time passing between the last scheduled run time of 12:05:00 and the current controller restart time of 12:06:05), then a single instance of the `CronWorkflow` will be executed exactly at 12:06:05.
+
+Currently only a single instance will be executed as a result of setting `startingDeadlineSeconds`.
+
+This setting can also be configured in tandem with `concurrencyPolicy` to achieve more fine-tuned control.
+
 ## Managing `CronWorkflow`
 
 ### CLI
diff --git a/docs/resource-duration.md b/docs/resource-duration.md
index 0351acdbf..f14926b12 100644
--- a/docs/resource-duration.md
+++ b/docs/resource-duration.md
@@ -20,7 +20,7 @@ Each indicator is divided by a common denominator depending on resource type.
 Each resource type has a denominator used to make large values smaller.
 
  * CPU: `1`
- * Memory: `100Mi`
+ * Memory: `1Gi`
  * Storage: `10Gi`
  * Ephemeral Storage: `10Gi`
  * All others: `1` 
diff --git a/hack/image_arch.sh b/hack/image_arch.sh
new file mode 100755
index 000000000..d87046bb4
--- /dev/null
+++ b/hack/image_arch.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+set -eu
+
+if [ "${IMAGE_OS}" = "linux" ]; then
+    export IMAGE_ARCH=`uname -m`;
+    if [ "${IMAGE_ARCH}" = "x86_64" ]; then
+        export IMAGE_ARCH=amd64;
+    elif [ "${IMAGE_ARCH}" = "aarch64" ]; then
+        export IMAGE_ARCH=arm64;
+    fi
+fi
diff --git a/ui/src/app/help/components/help.tsx b/ui/src/app/help/components/help.tsx
index ee77bacec..7bf22098e 100644
--- a/ui/src/app/help/components/help.tsx
+++ b/ui/src/app/help/components/help.tsx
@@ -32,25 +32,9 @@ export const Help = () => (
                 <div className='help-box'>
                     <div className='help-box__ico help-box__ico--download' />
                     <h3>Argo CLI</h3>
-                    <div className='row text-left help-box__download'>
-                        <div className='columns small-4'>
-                            <a href={`https://github.com/argoproj/argo/releases/download/${SYSTEM_INFO.version}/argo-linux-amd64`}>
-                                <i className='fab fa-linux' aria-hidden='true' /> Linux
-                            </a>
-                        </div>
-                        <div className='columns small-4'>
-                            <a href={`https://github.com/argoproj/argo/releases/download/${SYSTEM_INFO.version}/argo-darwin-amd64`}>
-                                <i className='fab fa-apple' aria-hidden='true' /> macOS
-                            </a>
-                            <br />
-                        </div>
-                        <div className='columns small-4'>
-                            <a href={`https://github.com/argoproj/argo/releases/download/${SYSTEM_INFO.version}/argo-windows-amd64`}>
-                                <i className='fab fa-windows' aria-hidden='true' /> Windows
-                            </a>
-                            <br />
-                        </div>
-                    </div>
+                    <a className='help-box__link' target='_blank' href='https://github.com/argoproj/argo/releases/latest'>
+                        Releases
+                    </a>
                 </div>
             </div>
         </div>
diff --git a/ui/src/app/shared/components/inline-table/inline-table.scss b/ui/src/app/shared/components/inline-table/inline-table.scss
new file mode 100644
index 000000000..b0336fbdc
--- /dev/null
+++ b/ui/src/app/shared/components/inline-table/inline-table.scss
@@ -0,0 +1,21 @@
+@import 'node_modules/argo-ui/src/styles/config';
+
+.it {
+  padding: 1em 0;
+  &--row {
+    display: flex;
+  }
+
+  &--col {
+    line-height: 2em;
+  }
+
+  &--key {
+    display: flex;
+    align-items: center;
+    border-right: 1px solid $argo-color-gray-3;
+    min-width: 150px;
+    padding-right: 10px;
+    margin-right: 10px;
+  }
+}
diff --git a/ui/src/app/shared/components/inline-table/inline-table.tsx b/ui/src/app/shared/components/inline-table/inline-table.tsx
new file mode 100644
index 000000000..be075827d
--- /dev/null
+++ b/ui/src/app/shared/components/inline-table/inline-table.tsx
@@ -0,0 +1,29 @@
+import * as React from 'react';
+import {ReactChild} from 'react';
+require('./inline-table.scss');
+
+interface TableProps {
+    rows: Row[];
+}
+
+interface Row {
+    left: ReactChild;
+    right: ReactChild;
+}
+
+export class InlineTable extends React.Component<TableProps> {
+    public render() {
+        return (
+            <div className='it'>
+                {this.props.rows.map((row, i) => {
+                    return (
+                        <div key={i} className='it--row'>
+                            <div className='it--col it--key'>{row.left}</div>
+                            <div className='it--col'>{row.right}</div>
+                        </div>
+                    );
+                })}
+            </div>
+        );
+    }
+}
diff --git a/ui/src/app/workflows/components/workflow-drawer/workflow-drawer.scss b/ui/src/app/workflows/components/workflow-drawer/workflow-drawer.scss
index feff08472..1d5d7c8ac 100644
--- a/ui/src/app/workflows/components/workflow-drawer/workflow-drawer.scss
+++ b/ui/src/app/workflows/components/workflow-drawer/workflow-drawer.scss
@@ -86,25 +86,10 @@
   }
 
   &__resourcesDuration {
-    display: flex;
-    align-items: center;
-
-    $gutter: 2em;
-
-    &--label {
-      margin-left: 0.5em;
-    }
-
     &--value {
-      font-weight: 600; 
-    }
-
-    &--container {
-      padding-left: $gutter / 2; 
-      margin-left: $gutter / 2; 
-      border-left: 1px solid $argo-color-gray-3;
+      font-weight: 600;
+      margin-right: 0.5em;
     }
-
   }
 
   &__conditions {
diff --git a/ui/src/app/workflows/components/workflow-drawer/workflow-drawer.tsx b/ui/src/app/workflows/components/workflow-drawer/workflow-drawer.tsx
index dc23aef7b..80bf48fe5 100644
--- a/ui/src/app/workflows/components/workflow-drawer/workflow-drawer.tsx
+++ b/ui/src/app/workflows/components/workflow-drawer/workflow-drawer.tsx
@@ -1,6 +1,7 @@
 import * as React from 'react';
 import {Workflow} from '../../../../models';
 
+import {InlineTable} from '../../../shared/components/inline-table/inline-table';
 import {Loading} from '../../../shared/components/loading';
 import {ConditionsPanel} from '../../../shared/conditions-panel';
 import {formatDuration} from '../../../shared/duration';
@@ -55,23 +56,33 @@ export class WorkflowDrawer extends React.Component<WorkflowDrawerProps, Workflo
                 )}
                 {!wf.status.resourcesDuration ? null : (
                     <div className='workflow-drawer__section'>
-                        <div className='workflow-drawer__resourcesDuration'>
-                            <div className='workflow-drawer__title'>
-                                RESOURCES DURATION&nbsp;
-                                <a href='https://argoproj.github.io/argo/resource-duration/' target='_blank'>
-                                    <i className='fas fa-info-circle' />
-                                </a>
-                            </div>
-                            <div className='workflow-drawer__resourcesDuration--container'>
-                                <div>
-                                    <span className='workflow-drawer__resourcesDuration--value'>{formatDuration(wf.status.resourcesDuration.cpu, 1)}</span>
-                                    <span className='workflow-drawer__resourcesDuration--label'>(*1 CPU)</span>
-                                </div>
-                                <div>
-                                    <span className='workflow-drawer__resourcesDuration--value'>{formatDuration(wf.status.resourcesDuration.memory, 1)}</span>
-                                    <span className='workflow-drawer__resourcesDuration--label'>(*100Mi Memory)</span>
-                                </div>
-                            </div>
+                        <div>
+                            <InlineTable
+                                rows={[
+                                    {
+                                        left: (
+                                            <div className='workflow-drawer__title'>
+                                                RESOURCES DURATION&nbsp;
+                                                <a href='https://github.com/argoproj/argo/blob/master/docs/resource-duration.md' target='_blank'>
+                                                    <i className='fas fa-info-circle' />
+                                                </a>
+                                            </div>
+                                        ),
+                                        right: (
+                                            <div>
+                                                <div>
+                                                    <span className='workflow-drawer__resourcesDuration--value'>{formatDuration(wf.status.resourcesDuration.cpu, 1)}</span>
+                                                    <span>(*1 CPU)</span>
+                                                </div>
+                                                <div>
+                                                    <span className='workflow-drawer__resourcesDuration--value'>{formatDuration(wf.status.resourcesDuration.memory, 1)}</span>
+                                                    <span>(*100Mi Memory)</span>
+                                                </div>
+                                            </div>
+                                        )
+                                    }
+                                ]}
+                            />
                         </div>
                     </div>
                 )}
diff --git a/ui/src/app/workflows/components/workflow-node-info/workflow-node-info.tsx b/ui/src/app/workflows/components/workflow-node-info/workflow-node-info.tsx
index 831cd1713..6dd4ec357 100644
--- a/ui/src/app/workflows/components/workflow-node-info/workflow-node-info.tsx
+++ b/ui/src/app/workflows/components/workflow-node-info/workflow-node-info.tsx
@@ -3,6 +3,7 @@ import * as moment from 'moment';
 import * as React from 'react';
 
 import * as models from '../../../../models';
+import {InlineTable} from '../../../shared/components/inline-table/inline-table';
 import {Phase} from '../../../shared/components/phase';
 import {Timestamp} from '../../../shared/components/timestamp';
 import {ResourcesDuration} from '../../../shared/resources-duration';
@@ -64,6 +65,27 @@ export const WorkflowNodeSummary = (props: Props) => {
                     {now => <Duration durationMs={nodeDuration(props.node, now)} />}
                 </Ticker>
             )
+        },
+        {
+            title: 'MEMOIZATION',
+            value: (
+                <InlineTable
+                    rows={[
+                        {
+                            left: <div> KEY </div>,
+                            right: <div> {props.node.memoizationStatus.key} </div>
+                        },
+                        {
+                            left: <div> CACHE NAME </div>,
+                            right: <div> {props.node.memoizationStatus.cacheName} </div>
+                        },
+                        {
+                            left: <div> HIT? </div>,
+                            right: <div> {props.node.memoizationStatus.hit ? 'YES' : 'NO'} </div>
+                        }
+                    ]}
+                />
+            )
         }
     ];
     if (props.node.type === 'Pod') {
diff --git a/ui/src/models/workflows.ts b/ui/src/models/workflows.ts
index 2d1ba4ad6..663148d38 100644
--- a/ui/src/models/workflows.ts
+++ b/ui/src/models/workflows.ts
@@ -520,6 +520,11 @@ export interface NodeStatus {
      * HostNodeName name of the Kubernetes node on which the Pod is running, if applicable.
      */
     hostNodeName: string;
+
+    /**
+     * Memoization
+     */
+    memoizationStatus: MemoizationStatus;
 }
 
 export interface TemplateRef {
@@ -777,6 +782,25 @@ export interface WorkflowStep {
     templateRef?: TemplateRef;
 }
 
+/**
+ * MemoizationStatus holds information about a node with memoization enabled.
+ */
+
+export interface MemoizationStatus {
+    /**
+     * Hit is true if there was a previous cache entry and false otherwise
+     */
+    hit: boolean;
+    /**
+     * Key is the value used to query the cache for an entry
+     */
+    key: string;
+    /**
+     * Cache name stores the identifier of the cache used for this node
+     */
+    cacheName: string;
+}
+
 export type NodePhase = 'Pending' | 'Running' | 'Succeeded' | 'Skipped' | 'Failed' | 'Error' | 'Omitted';
 
 export const NODE_PHASE = {
diff --git a/workflow/controller/dag.go b/workflow/controller/dag.go
index 7e7a31e94..b627f4869 100644
--- a/workflow/controller/dag.go
+++ b/workflow/controller/dag.go
@@ -158,12 +158,9 @@ func (d *dagContext) assessDAGPhase(targetTasks []string, nodes wfv1.Nodes) wfv1
 			}
 		}
 
-		if node.Type == wfv1.NodeTypeRetry || node.Type == wfv1.NodeTypeTaskGroup {
+		if node.Type == wfv1.NodeTypeRetry {
 			// A fulfilled Retry node will always reflect the status of its last child node, so its individual attempts don't interest us.
 			// To resume the traversal, we look at the children of the last child node.
-			// A TaskGroup node will always reflect the status of its expanded tasks (mainly it will be Succeeded if and only if all of its
-			// expanded tasks have succeeded), so each individual expanded task doesn't interest us. To resume the traversal, we look at the
-			// children of its last child node (note that this is arbitrary, since all expanded tasks will have the same children).
 			if childNode := getChildNodeIndex(&node, nodes, -1); childNode != nil {
 				uniqueQueue.add(generatePhaseNodes(childNode.Children, branchPhase)...)
 			}
diff --git a/workflow/controller/workflowpod.go b/workflow/controller/workflowpod.go
index b01c5ffe8..deda1799b 100644
--- a/workflow/controller/workflowpod.go
+++ b/workflow/controller/workflowpod.go
@@ -394,6 +394,7 @@ func (woc *wfOperationCtx) newWaitContainer(tmpl *wfv1.Template) (*apiv1.Contain
 				Add: []apiv1.Capability{
 					// necessary to access main's root filesystem when run with a different user id
 					apiv1.Capability("SYS_PTRACE"),
+					apiv1.Capability("SYS_CHROOT"),
 				},
 			},
 		}


Test patch:
diff --git a/workflow/controller/dag_test.go b/workflow/controller/dag_test.go
index c29c90d40..d7f9e9f2f 100644
--- a/workflow/controller/dag_test.go
+++ b/workflow/controller/dag_test.go
@@ -2030,3 +2030,827 @@ func TestDagTargetTaskOnExit(t *testing.T) {
 		assert.Equal(t, wfv1.NodePending, onExitNode.Phase)
 	}
 }
+
+var testEmptyWithParamDAG = `
+apiVersion: argoproj.io/v1alpha1
+kind: Workflow
+metadata:
+  name: dag-hang-pcwmr
+spec:
+  arguments: {}
+  entrypoint: dag
+  templates:
+  - arguments: {}
+    dag:
+      tasks:
+      - arguments: {}
+        name: scheduler
+        template: job-scheduler
+      - arguments:
+          parameters:
+          - name: job_name
+            value: '{{item.job_name}}'
+        dependencies:
+        - scheduler
+        name: children
+        template: whalesay
+        withParam: '{{tasks.scheduler.outputs.parameters.scheduled-jobs}}'
+      - arguments: {}
+        dependencies:
+        - children
+        name: postprocess
+        template: whalesay
+    inputs: {}
+    metadata: {}
+    name: dag
+    outputs: {}
+  - arguments: {}
+    container:
+      args:
+      - echo Decided not to schedule any jobs
+      command:
+      - sh
+      - -c
+      image: alpine:latest
+      name: ""
+      resources: {}
+    inputs: {}
+    metadata: {}
+    name: job-scheduler
+    outputs:
+      parameters:
+      - name: scheduled-jobs
+        value: '[]'
+  - arguments: {}
+    container:
+      args:
+      - hello world
+      command:
+      - cowsay
+      image: docker/whalesay
+      name: ""
+      resources: {}
+    inputs: {}
+    metadata: {}
+    name: whalesay
+    outputs: {}
+status:
+  finishedAt: null
+  nodes:
+    dag-hang-pcwmr:
+      children:
+      - dag-hang-pcwmr-1789179473
+      displayName: dag-hang-pcwmr
+      finishedAt: null
+      id: dag-hang-pcwmr
+      name: dag-hang-pcwmr
+      phase: Running
+      startedAt: "2020-08-11T18:19:28Z"
+      templateName: dag
+      templateScope: local/dag-hang-pcwmr
+      type: DAG
+    dag-hang-pcwmr-1415348083:
+      boundaryID: dag-hang-pcwmr
+      displayName: postprocess
+      finishedAt: "2020-08-11T18:19:40Z"
+      hostNodeName: dech117
+      id: dag-hang-pcwmr-1415348083
+      name: dag-hang-pcwmr.postprocess
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 3
+        memory: 3
+      startedAt: "2020-08-11T18:19:36Z"
+      templateName: whalesay
+      templateScope: local/dag-hang-pcwmr
+      type: Pod
+    dag-hang-pcwmr-1738428083:
+      boundaryID: dag-hang-pcwmr
+      children:
+      - dag-hang-pcwmr-1415348083
+      displayName: children
+      finishedAt: "2020-08-11T18:19:35Z"
+      id: dag-hang-pcwmr-1738428083
+      name: dag-hang-pcwmr.children
+      phase: Succeeded
+      startedAt: "2020-08-11T18:19:35Z"
+      templateName: whalesay
+      templateScope: local/dag-hang-pcwmr
+      type: TaskGroup
+    dag-hang-pcwmr-1789179473:
+      boundaryID: dag-hang-pcwmr
+      children:
+      - dag-hang-pcwmr-1738428083
+      displayName: scheduler
+      finishedAt: "2020-08-11T18:19:33Z"
+      hostNodeName: dech113
+      id: dag-hang-pcwmr-1789179473
+      name: dag-hang-pcwmr.scheduler
+      outputs:
+        exitCode: "0"
+        parameters:
+        - name: scheduled-jobs
+          value: '[]'
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 4
+        memory: 4
+      startedAt: "2020-08-11T18:19:28Z"
+      templateName: job-scheduler
+      templateScope: local/dag-hang-pcwmr
+      type: Pod
+  phase: Running
+  startedAt: "2020-08-11T18:19:28Z"
+`
+
+func TestEmptyWithParamDAG(t *testing.T) {
+	cancel, controller := newController()
+	defer cancel()
+	wfcset := controller.wfclientset.ArgoprojV1alpha1().Workflows("")
+
+	wf := unmarshalWF(testEmptyWithParamDAG)
+	wf, err := wfcset.Create(wf)
+	assert.NoError(t, err)
+	woc := newWorkflowOperationCtx(wf, controller)
+
+	woc.operate()
+	assert.Equal(t, wfv1.NodeSucceeded, woc.wf.Status.Phase)
+}
+
+var testFailsWithParamDAG = `
+apiVersion: argoproj.io/v1alpha1
+kind: Workflow
+metadata:
+  name: reproduce-bug-9tpfr
+spec:
+  arguments: {}
+  entrypoint: start
+  serviceAccountName: argo-workflow
+  templates:
+  - arguments: {}
+    dag:
+      tasks:
+      - arguments: {}
+        name: gen-tasks
+        template: gen-tasks
+      - arguments:
+          parameters:
+          - name: chunk
+            value: '{{item}}'
+        dependencies:
+        - gen-tasks
+        name: process-tasks
+        template: process-tasks
+        withParam: '{{tasks.gen-tasks.outputs.result}}'
+      - arguments: {}
+        dependencies:
+        - process-tasks
+        name: finish
+        template: finish
+    inputs: {}
+    metadata: {}
+    name: start
+    outputs: {}
+  - activeDeadlineSeconds: 300
+    arguments: {}
+    inputs: {}
+    metadata: {}
+    name: gen-tasks
+    outputs: {}
+    retryStrategy:
+      backoff:
+        duration: 15s
+        factor: 2
+      limit: 5
+      retryPolicy: Always
+    script:
+      command:
+      - bash
+      image: python:3
+      name: ""
+      resources:
+        requests:
+          cpu: 250m
+      source: |
+        set -e
+        python3 -c 'import os, json; print(json.dumps([str(i) for i in range(10)]))'
+  - activeDeadlineSeconds: 1800
+    arguments: {}
+    inputs:
+      parameters:
+      - name: chunk
+    metadata: {}
+    name: process-tasks
+    outputs: {}
+    retryStrategy:
+      backoff:
+        duration: 15s
+        factor: 2
+      limit: 2
+      retryPolicy: Always
+    script:
+      command:
+      - bash
+      image: python:3
+      name: ""
+      resources:
+        requests:
+          cpu: 100m
+      source: |
+        set -e
+        chunk="{{inputs.parameters.chunk}}"
+        if [[ $chunk == "3" ]]; then
+          echo "failed"
+          exit 1
+        fi
+        echo "process $chunk"
+  - activeDeadlineSeconds: 300
+    arguments: {}
+    inputs: {}
+    metadata: {}
+    name: finish
+    outputs: {}
+    script:
+      command:
+      - sh
+      image: busybox
+      name: ""
+      resources:
+        requests:
+          cpu: 100m
+      source: |
+        echo fin
+status:
+  nodes:
+    reproduce-bug-9tpfr:
+      children:
+      - reproduce-bug-9tpfr-1525049382
+      displayName: reproduce-bug-9tpfr
+      finishedAt: "2020-08-14T03:49:42Z"
+      id: reproduce-bug-9tpfr
+      name: reproduce-bug-9tpfr
+      outboundNodes:
+      - reproduce-bug-9tpfr-247809182
+      phase: Running
+      startedAt: "2020-08-14T03:47:23Z"
+      templateName: start
+      templateScope: local/reproduce-bug-9tpfr
+      type: DAG
+    reproduce-bug-9tpfr-247809182:
+      boundaryID: reproduce-bug-9tpfr
+      displayName: finish
+      finishedAt: "2020-08-14T03:49:42Z"
+      id: reproduce-bug-9tpfr-247809182
+      message: 'omitted: depends condition not met'
+      name: reproduce-bug-9tpfr.finish
+      phase: Omitted
+      startedAt: "2020-08-14T03:49:42Z"
+      templateName: finish
+      templateScope: local/reproduce-bug-9tpfr
+      type: Skipped
+    reproduce-bug-9tpfr-546685502:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-3207714925
+      displayName: process-tasks(6:6)
+      finishedAt: "2020-08-14T03:47:37Z"
+      id: reproduce-bug-9tpfr-546685502
+      inputs:
+        parameters:
+        - name: chunk
+          value: "6"
+      name: reproduce-bug-9tpfr.process-tasks(6:6)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:30Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-585646929:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(7:7)(0)
+      finishedAt: "2020-08-14T03:47:33Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-c3910e16-nb0l
+      id: reproduce-bug-9tpfr-585646929
+      inputs:
+        parameters:
+        - name: chunk
+          value: "7"
+      name: reproduce-bug-9tpfr.process-tasks(7:7)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 1
+        memory: 1
+      startedAt: "2020-08-14T03:47:30Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-600389385:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(5:5)(0)
+      finishedAt: "2020-08-14T03:47:33Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-c3910e16-nb0l
+      id: reproduce-bug-9tpfr-600389385
+      inputs:
+        parameters:
+        - name: chunk
+          value: "5"
+      name: reproduce-bug-9tpfr.process-tasks(5:5)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 1
+        memory: 1
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-850457006:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-3450100829
+      displayName: process-tasks(2:2)
+      finishedAt: "2020-08-14T03:47:36Z"
+      id: reproduce-bug-9tpfr-850457006
+      inputs:
+        parameters:
+        - name: chunk
+          value: "2"
+      name: reproduce-bug-9tpfr.process-tasks(2:2)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-988357889:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(1:1)(0)
+      finishedAt: "2020-08-14T03:47:34Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-3779d805-hkcv
+      id: reproduce-bug-9tpfr-988357889
+      inputs:
+        parameters:
+        - name: chunk
+          value: "1"
+      name: reproduce-bug-9tpfr.process-tasks(1:1)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 2
+        memory: 2
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-1384515437:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(8:8)(0)
+      finishedAt: "2020-08-14T03:47:42Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-2e8afe0d-km90
+      id: reproduce-bug-9tpfr-1384515437
+      inputs:
+        parameters:
+        - name: chunk
+          value: "8"
+      name: reproduce-bug-9tpfr.process-tasks(8:8)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 6
+        memory: 6
+      startedAt: "2020-08-14T03:47:30Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-1525049382:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-3595395365
+      displayName: gen-tasks
+      finishedAt: "2020-08-14T03:47:29Z"
+      id: reproduce-bug-9tpfr-1525049382
+      name: reproduce-bug-9tpfr.gen-tasks
+      outputs:
+        exitCode: "0"
+        result: '["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]'
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:23Z"
+      templateName: gen-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-1602779214:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-3522592509
+      displayName: process-tasks(4:4)
+      finishedAt: "2020-08-14T03:47:45Z"
+      id: reproduce-bug-9tpfr-1602779214
+      inputs:
+        parameters:
+        - name: chunk
+          value: "4"
+      name: reproduce-bug-9tpfr.process-tasks(4:4)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-1670762753:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-2788826366
+      - reproduce-bug-9tpfr-3412607194
+      - reproduce-bug-9tpfr-850457006
+      - reproduce-bug-9tpfr-3505932898
+      - reproduce-bug-9tpfr-1602779214
+      - reproduce-bug-9tpfr-4143798034
+      - reproduce-bug-9tpfr-546685502
+      - reproduce-bug-9tpfr-3415721642
+      - reproduce-bug-9tpfr-3221614398
+      - reproduce-bug-9tpfr-3518128714
+      displayName: process-tasks
+      finishedAt: "2020-08-14T03:49:42Z"
+      id: reproduce-bug-9tpfr-1670762753
+      name: reproduce-bug-9tpfr.process-tasks
+      phase: Failed
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: TaskGroup
+    reproduce-bug-9tpfr-2008331609:
+      boundaryID: reproduce-bug-9tpfr
+      displayName: process-tasks(3:3)(0)
+      finishedAt: "2020-08-14T03:47:42Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-2e8afe0d-km90
+      id: reproduce-bug-9tpfr-2008331609
+      inputs:
+        parameters:
+        - name: chunk
+          value: "3"
+      message: failed with exit code 1
+      name: reproduce-bug-9tpfr.process-tasks(3:3)(0)
+      outputs:
+        exitCode: "1"
+      phase: Failed
+      resourcesDuration:
+        cpu: 6
+        memory: 6
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-2475724017:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(9:9)(0)
+      finishedAt: "2020-08-14T03:47:34Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-3779d805-hkcv
+      id: reproduce-bug-9tpfr-2475724017
+      inputs:
+        parameters:
+        - name: chunk
+          value: "9"
+      name: reproduce-bug-9tpfr.process-tasks(9:9)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 1
+        memory: 1
+      startedAt: "2020-08-14T03:47:30Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-2612472988:
+      boundaryID: reproduce-bug-9tpfr
+      displayName: process-tasks(3:3)(1)
+      finishedAt: "2020-08-14T03:48:05Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-2e8afe0d-km90
+      id: reproduce-bug-9tpfr-2612472988
+      inputs:
+        parameters:
+        - name: chunk
+          value: "3"
+      message: failed with exit code 1
+      name: reproduce-bug-9tpfr.process-tasks(3:3)(1)
+      outputs:
+        exitCode: "1"
+      phase: Failed
+      resourcesDuration:
+        cpu: 2
+        memory: 2
+      startedAt: "2020-08-14T03:48:00Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-2788826366:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-3662458541
+      displayName: process-tasks(0:0)
+      finishedAt: "2020-08-14T03:47:44Z"
+      id: reproduce-bug-9tpfr-2788826366
+      inputs:
+        parameters:
+        - name: chunk
+          value: "0"
+      name: reproduce-bug-9tpfr.process-tasks(0:0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-3207714925:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(6:6)(0)
+      finishedAt: "2020-08-14T03:47:34Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-3779d805-hkcv
+      id: reproduce-bug-9tpfr-3207714925
+      inputs:
+        parameters:
+        - name: chunk
+          value: "6"
+      name: reproduce-bug-9tpfr.process-tasks(6:6)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 2
+        memory: 2
+      startedAt: "2020-08-14T03:47:30Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-3221614398:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-1384515437
+      displayName: process-tasks(8:8)
+      finishedAt: "2020-08-14T03:47:44Z"
+      id: reproduce-bug-9tpfr-3221614398
+      inputs:
+        parameters:
+        - name: chunk
+          value: "8"
+      name: reproduce-bug-9tpfr.process-tasks(8:8)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:30Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-3412607194:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-988357889
+      displayName: process-tasks(1:1)
+      finishedAt: "2020-08-14T03:47:36Z"
+      id: reproduce-bug-9tpfr-3412607194
+      inputs:
+        parameters:
+        - name: chunk
+          value: "1"
+      name: reproduce-bug-9tpfr.process-tasks(1:1)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-3415721642:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-585646929
+      displayName: process-tasks(7:7)
+      finishedAt: "2020-08-14T03:47:36Z"
+      id: reproduce-bug-9tpfr-3415721642
+      inputs:
+        parameters:
+        - name: chunk
+          value: "7"
+      name: reproduce-bug-9tpfr.process-tasks(7:7)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:30Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-3450100829:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(2:2)(0)
+      finishedAt: "2020-08-14T03:47:33Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-3779d805-hkcv
+      id: reproduce-bug-9tpfr-3450100829
+      inputs:
+        parameters:
+        - name: chunk
+          value: "2"
+      name: reproduce-bug-9tpfr.process-tasks(2:2)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 1
+        memory: 1
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-3505932898:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-2008331609
+      - reproduce-bug-9tpfr-2612472988
+      - reproduce-bug-9tpfr-4222579959
+      displayName: process-tasks(3:3)
+      finishedAt: "2020-08-14T03:49:42Z"
+      id: reproduce-bug-9tpfr-3505932898
+      inputs:
+        parameters:
+        - name: chunk
+          value: "3"
+      message: No more retries left
+      name: reproduce-bug-9tpfr.process-tasks(3:3)
+      phase: Failed
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-3518128714:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-2475724017
+      displayName: process-tasks(9:9)
+      finishedAt: "2020-08-14T03:47:37Z"
+      id: reproduce-bug-9tpfr-3518128714
+      inputs:
+        parameters:
+        - name: chunk
+          value: "9"
+      name: reproduce-bug-9tpfr.process-tasks(9:9)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:30Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-3522592509:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(4:4)(0)
+      finishedAt: "2020-08-14T03:47:42Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-2e8afe0d-km90
+      id: reproduce-bug-9tpfr-3522592509
+      inputs:
+        parameters:
+        - name: chunk
+          value: "4"
+      name: reproduce-bug-9tpfr.process-tasks(4:4)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 6
+        memory: 6
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-3595395365:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-1670762753
+      displayName: gen-tasks(0)
+      finishedAt: "2020-08-14T03:47:26Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-3779d805-hkcv
+      id: reproduce-bug-9tpfr-3595395365
+      name: reproduce-bug-9tpfr.gen-tasks(0)
+      outputs:
+        exitCode: "0"
+        result: '["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]'
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 1
+        memory: 1
+      startedAt: "2020-08-14T03:47:23Z"
+      templateName: gen-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-3662458541:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(0:0)(0)
+      finishedAt: "2020-08-14T03:47:42Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-2e8afe0d-km90
+      id: reproduce-bug-9tpfr-3662458541
+      inputs:
+        parameters:
+        - name: chunk
+          value: "0"
+      name: reproduce-bug-9tpfr.process-tasks(0:0)(0)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      resourcesDuration:
+        cpu: 6
+        memory: 6
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+    reproduce-bug-9tpfr-4143798034:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-600389385
+      displayName: process-tasks(5:5)
+      finishedAt: "2020-08-14T03:47:36Z"
+      id: reproduce-bug-9tpfr-4143798034
+      inputs:
+        parameters:
+        - name: chunk
+          value: "5"
+      name: reproduce-bug-9tpfr.process-tasks(5:5)
+      outputs:
+        exitCode: "0"
+      phase: Succeeded
+      startedAt: "2020-08-14T03:47:29Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Retry
+    reproduce-bug-9tpfr-4222579959:
+      boundaryID: reproduce-bug-9tpfr
+      children:
+      - reproduce-bug-9tpfr-247809182
+      displayName: process-tasks(3:3)(2)
+      finishedAt: "2020-08-14T03:48:40Z"
+      hostNodeName: gke-dotdb3-dotdb-pool-3779d805-hkcv
+      id: reproduce-bug-9tpfr-4222579959
+      inputs:
+        parameters:
+        - name: chunk
+          value: "3"
+      message: failed with exit code 1
+      name: reproduce-bug-9tpfr.process-tasks(3:3)(2)
+      outputs:
+        exitCode: "1"
+      phase: Failed
+      resourcesDuration:
+        cpu: 1
+        memory: 1
+      startedAt: "2020-08-14T03:48:37Z"
+      templateName: process-tasks
+      templateScope: local/reproduce-bug-9tpfr
+      type: Pod
+  phase: Running
+  resourcesDuration:
+    cpu: 36
+    memory: 36
+  startedAt: "2020-08-14T03:47:23Z"
+`
+
+func TestFailsWithParamDAG(t *testing.T) {
+	cancel, controller := newController()
+	defer cancel()
+	wfcset := controller.wfclientset.ArgoprojV1alpha1().Workflows("")
+
+	wf := unmarshalWF(testFailsWithParamDAG)
+	wf, err := wfcset.Create(wf)
+	assert.NoError(t, err)
+	woc := newWorkflowOperationCtx(wf, controller)
+
+	woc.operate()
+	assert.Equal(t, wfv1.NodeFailed, woc.wf.Status.Phase)
+}