{"id":17983030,"url":"https://github.com/minghsu0107/argo-workflow-quickstart","last_synced_at":"2025-08-19T23:06:39.677Z","repository":{"id":44407258,"uuid":"512502212","full_name":"minghsu0107/argo-workflow-quickstart","owner":"minghsu0107","description":"A quick start guide for Argo Workflow.","archived":false,"fork":false,"pushed_at":"2022-12-12T18:50:45.000Z","size":167,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T02:11:39.728Z","etag":null,"topics":["argo-workflow","kubernetes"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/minghsu0107.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-10T17:52:27.000Z","updated_at":"2024-01-12T18:33:05.000Z","dependencies_parsed_at":"2023-01-27T23:40:17.169Z","dependency_job_id":null,"html_url":"https://github.com/minghsu0107/argo-workflow-quickstart","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/minghsu0107/argo-workflow-quickstart","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minghsu0107%2Fargo-workflow-quickstart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minghsu0107%2Fargo-workflow-quickstart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minghsu0107%2Fargo-workflow-quickstart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minghsu0107%2Fargo-workflow-quickstart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/minghsu0107","download_url":"https://codeload.github.com/minghsu0107/argo-workflow-quickstart/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minghsu0107%2Fargo-workflow-quickstart/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271236280,"owners_count":24723978,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-19T02:00:09.176Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["argo-workflow","kubernetes"],"created_at":"2024-10-29T18:15:53.699Z","updated_at":"2025-08-19T23:06:39.644Z","avatar_url":"https://github.com/minghsu0107.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# argo-workflow-quickstart\nScripts are referenced from https://github.com/argoproj/argo-workflows/tree/master/examples\n## Installation\n- https://github.com/argoproj/argo-workflows/releases/tag/v3.3.8\n- https://argoproj.github.io/argo-workflows/installation/\n    - [Configuration](https://argoproj.github.io/argo-workflows/environment-variables/)\n        - https://argoproj.github.io/argo-workflows/workflow-controller-configmap.yaml\n            - configure `resourceRateLimit` to mitigate flooding of the Kubernetes API server by workflows with a large amount of parallel nodes\n    - [Prometheus Metrics](https://argoproj.github.io/argo-workflows/metrics/)\n    - [Argo Server Auth](https://argoproj.github.io/argo-workflows/argo-server-auth-mode/)\n        - [Token Creation for Client Authentication](https://argoproj.github.io/argo-workflows/access-token/#token-creation)\n\nCreate an admin serviceaccount:\n```yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: argoadmin\n  namespace: argo\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: argoadmin\nsubjects:\n- kind: ServiceAccount\n  name: argoadmin\n  namespace: argo\nroleRef:\n  kind: ClusterRole\n  name: admin # default k8s cluster admin role\n  apiGroup: rbac.authorization.k8s.io\n```\n```bash\nSECRET=$(kubectl get sa argoadmin -n argo -o=jsonpath='{.secrets[0].name}')\nARGO_TOKEN=\"Bearer $(kubectl get secret $SECRET -n argo -o=jsonpath='{.data.token}' | base64 --decode)\"\necho $ARGO_TOKEN\n```\n\nRemember to override `workflow-controller-configmap` with https://argoproj.github.io/argo-workflows/workflow-controller-configmap.yaml in order to configure Postgres (for job results) and S3 (for job logs). Then you can apply the manifests:\n```bash\nkubectl create namespace argo\nkubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.3.8/install.yaml\n```\nWeb UI: https://localhost:2746\n\nOpen port-forward to access the UI:\n```bash\nkubectl -n argo port-forward deployment/argo-server 2746:2746\n```\n### Default Workflow Configuration\nFor the following workflow setting:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: gc-ttl-\n  annotations:\n    argo: workflows\n  labels:\n    foo: bar\nspec:\n  ttlStrategy:\n    secondsAfterSuccess: 5  # Time to live after workflow is successful\n  parallelism: 3\n```\nYou can set it as the default value in `workflow-controller-configmap`:\n```yaml\n# This file describes the config settings available in the workflow controller configmap\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: workflow-controller-configmap\ndata:\n  # Default values that will apply to all Workflows from this controller, unless overridden on the Workflow-level\n  workflowDefaults: |\n    metadata:\n      annotations:\n        argo: workflows\n      labels:\n        foo: bar\n    spec:\n      ttlStrategy:\n        secondsAfterSuccess: 5\n      parallelism: 3\n```\n### Other Configuration\nSecurity context:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: security-context-\nspec:\n  securityContext:\n    runAsNonRoot: true\n    runAsUser: 8737 #; any non-root user\n```\n## Argo CLI\n```bash\nargo submit -n argo hello-world.yaml    # submit a workflow spec to Kubernetes\nargo list -n argo                       # list current workflows\nargo get hello-world-xxx -n argo        # get info about a specific workflow\nargo logs hello-world-xxx -n argo       # print the logs from a workflow\nargo delete hello-world-xxx -n argo     # delete workflow\n```\nYou can also run workflow specs directly using `kubectl`:\n```bash\nkubectl create -f hello-world.yaml -n argo\nkubectl get wf -n argo\nkubectl get wf hello-world-xxx -n argo\nkubectl get po --selector=workflows.argoproj.io/workflow=hello-world-xxx --show-all -n argo  # similar to argo\nkubectl logs hello-world-xxx-yyy -c main -n argo\nkubectl delete wf hello-world-xxx -n argo\n```\nNote that we should use `kubectl create` instead of `kubectl apply`. Otherwise the workflow will run only once even if you modify its manifest later.\n## Usage\nExample job:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: hello-world-\n  labels:\n    workflows.argoproj.io/archive-strategy: \"false\"\n  annotations:\n    workflows.argoproj.io/description: |\n      This is a simple hello world example.\nspec:\n  # # Defines \"whalesay\" as the \"main\" template\n  entrypoint: whalesay\n  templates:\n  - name: whalesay\n    container:\n      image: docker/whalesay:latest\n      command: [cowsay]\n      args: [\"hello world\"]\n```\nSubmit a job with serviceaccount `argoadmin`:\n```bash\nargo submit --serviceaccount argoadmin -n argo --watch hello-world.yaml\n```\nList workflows:\n```bash\nargo list -n argo --kubeconfig /path/to/kubeconfig --context k3d-k3s-default\n```\nGet latest workflow details:\n```bash\nargo get -n argo @latest\n```\nGet latest workflow logs:\n```bash\nargo logs -n argo @latest\n```\n## Workflow Example\n### If-Else\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: coinflip-\nspec:\n  entrypoint: coinflip\n  templates:\n  - name: coinflip\n    steps:\n    - - name: flip-coin\n        template: flip-coin\n    - - name: heads\n        template: heads\n        when: \"{{steps.flip-coin.outputs.result}} == heads\"\n      - name: tails\n        template: tails\n        when: \"{{steps.flip-coin.outputs.result}} == tails\"\n\n  - name: flip-coin\n    script:\n      image: python:alpine3.6\n      command: [python]\n      source: |\n        import random\n        result = \"heads\" if random.randint(0,1) == 0 else \"tails\"\n        print(result)\n\n  - name: heads\n    container:\n      image: alpine:3.6\n      command: [sh, -c]\n      args: [\"echo \\\"it was heads\\\"\"]\n\n  - name: tails\n    container:\n      image: alpine:3.6\n      command: [sh, -c]\n      args: [\"echo \\\"it was tails\\\"\"]\n```\n### DAG\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: dag-diamond-\nspec:\n  entrypoint: diamond\n  templates:\n  - name: diamond\n    dag:\n      tasks:\n      - name: A\n        template: echo\n        arguments:\n          parameters: [{name: message, value: A}]\n      - name: B\n        dependencies: [A]\n        template: echo\n        arguments:\n          parameters: [{name: message, value: B}]\n      - name: C\n        dependencies: [A]\n        template: echo\n        arguments:\n          parameters: [{name: message, value: C}]\n      - name: D\n        dependencies: [B, C]\n        template: echo\n        arguments:\n          parameters: [{name: message, value: D}]\n  #- name: diamond\n  #    steps:\n  #    - - name: A\n  #        template: echo\n  #        arguments:\n  #          parameters: [{name: message, value: A}]\n  #    - - name: B\n  #        template: echo\n  #        arguments:\n  #          parameters: [{name: message, value: B}]\n  #      - name: C\n  #        template: echo\n  #        arguments:\n  #          parameters: [{name: message, value: C}]\n  #    - - name: D\n  #        template: echo\n  #        arguments:\n  #          parameters: [{name: message, value: D}]\n\n  - name: echo\n    inputs:\n      parameters:\n      - name: message\n    container:\n      image: alpine:3.7\n      command: [echo, \"{{inputs.parameters.message}}\"]\n```\n### Artifacts and Parameters\nDifferent types of inputs + passing artifacts and parameters + argument from command line:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: example-\nspec:\n  entrypoint: main\n  # in global\n  arguments:\n    parameters:\n    - name: workflow-param-1\n  templates:\n  - name: main\n    dag:\n      tasks:\n      - name: step-a\n        template: step-template-a\n        # in dag\n        arguments:\n          parameters:\n          - name: template-param-1\n            value: \"{{workflow.parameters.workflow-param-1}}\"\n      - name: step-b\n        dependencies: [step-a]\n        template: step-template-b\n        arguments:\n          parameters:\n          - name: template-param-2\n            value: \"{{tasks.step-a.outputs.parameters.output-param-1}}\"\n          artifacts:\n          - name: input-artifact-2\n            from: \"{{tasks.step-a.outputs.artifacts.output-artifact-1}}\"\n\n  - name: step-template-a\n    # in template\n    inputs:\n      parameters:\n        - name: template-param-1\n    script:\n      image: alpine:3.14\n      command: [/bin/sh]\n      source: |\n          echo \"{{inputs.parameters.template-param-1}}\" | tee /p1.txt\n          echo \"my message\" \u003e /tmp/message\n    outputs:\n      parameters:\n        - name: output-param-1\n          valueFrom:\n            path: /p1.txt\n      artifacts:\n        - name: output-artifact-1\n          path: /tmp/message\n  - name: step-template-b\n    inputs:\n      parameters:\n      - name: template-param-2\n      artifacts:\n      - name: input-artifact-2\n        path: /tmp/message\n    script:\n      image: alpine:3.14\n      command: [/bin/sh]\n      source: |\n          echo \"{{inputs.parameters.template-param-2}}\"\n          cat /tmp/message\n```\nCreate workflow:\n```bash\nargo submit --serviceaccount argoadmin -n argo example.yaml -p 'workflow-param-1=\"abcd\"'\n```\nAnother example:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: conditional-\nspec:\n  entrypoint: conditional-example\n  # global arg\n  arguments:\n    parameters:\n    - name: should-print\n      value: \"false\"\n\n  templates:\n  # in template\n  - name: conditional-example\n    inputs:\n      parameters:\n      - name: should-print\n    steps:\n    - - name: print-hello\n        template: whalesay\n        # when: \"{{workflow.parameters.should-print}} == true\"\n        when: \"{{inputs.parameters.should-print}} == true\"\n\n  - name: whalesay\n    container:\n      image: docker/whalesay:latest\n      command: [sh, -c]\n      args: [\"cowsay hello\"]\n```\nPass argument:\n```bash\nargo submit examples/conditionals.yaml -n argo -p should-print=true\n```\nGet result from last step:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: retry-script-\nspec:\n  entrypoint: main\n  templates:\n    - name: main\n      steps:\n        - - name: safe-to-retry\n            template: safe-to-retry\n        - - name: retry\n            template: retry-script\n            # in steps\n            arguments:\n              parameters:\n                - name: safe-to-retry\n                  value: \"{{steps.safe-to-retry.outputs.result}}\"\n\n    - name: safe-to-retry\n      script:\n        image: python:alpine3.6\n        command: [\"python\"]\n        source: |\n          print(\"true\")\n    - name: retry-script\n      inputs:\n        parameters:\n            - name: safe-to-retry\n      retryStrategy:\n        limit: \"3\"\n        # Only continue retrying if the last exit code is greater than 1 and the input parameter is true\n        expression: \"asInt(lastRetry.exitCode) \u003e 1 \u0026\u0026 {{inputs.parameters.safe-to-retry}} == true\"\n      script:\n        image: python:alpine3.6\n        command: [\"python\"]\n        # Exit 1 with 50% probability and 2 with 50%\n        source: |\n          import random;\n          import sys;\n          exit_code = random.choice([1, 2]);\n          sys.exit(exit_code)\n```\n### Conditional Artifacts and Parameters\n- https://argoproj.github.io/argo-workflows/conditional-artifacts-parameters/\n\nConditional artifacts:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: conditional-artifacts-\n  labels:\n    workflows.argoproj.io/test: \"true\"\n  annotations:\n    workflows.argoproj.io/description: |\n      Conditional aartifacts provide a way to choose the output artifacts based on expression.\n\n      In this example the main template has two steps which will run conditionall using `when` .\n\n      Based on the `when` condition one of step will not execute. The main template's output artifact named \"result\"\n      will be set to the executed step's output.\n    workflows.argoproj.io/version: '\u003e= 3.1.0'\nspec:\n  entrypoint: main\n  templates:\n    - name: main\n      steps:\n        - - name: flip-coin\n            template: flip-coin\n        - - name: heads\n            template: heads\n            when: \"{{steps.flip-coin.outputs.result}} == heads\"\n          - name: tails\n            template: tails\n            when: \"{{steps.flip-coin.outputs.result}} == tails\"\n      outputs:\n        artifacts:\n          - name: result\n            fromExpression: \"steps['flip-coin'].outputs.result == 'heads' ? steps.heads.outputs.artifacts.result : steps.tails.outputs.artifacts.result\"\n\n    - name: flip-coin\n      script:\n        image: python:alpine3.6\n        command: [ python ]\n        source: |\n          import random\n          print(\"heads\" if random.randint(0,1) == 0 else \"tails\")\n\n    - name: heads\n      script:\n        image: python:alpine3.6\n        command: [ python ]\n        source: |\n          with open(\"result.txt\", \"w\") as f:\n            f.write(\"it was heads\")\n      outputs:\n        artifacts:\n          - name: result\n            path: /result.txt\n\n    - name: tails\n      script:\n        image: python:alpine3.6\n        command: [ python ]\n        source: |\n          with open(\"result.txt\", \"w\") as f:\n            f.write(\"it was tails\")\n      outputs:\n        artifacts:\n          - name: result\n            path: /result.txt\n```\n### Retry\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: retry-backoff-\nspec:\n  entrypoint: retry-backoff\n  templates:\n  - name: retry-backoff\n    retryStrategy:\n      limit: \"10\"\n      backoff:\n        duration: \"1\"       # Must be a string. Default unit is seconds. Could also be a Duration, e.g.: \"2m\", \"6h\", \"1d\"\n        factor: \"2\"\n        maxDuration: \"1m\" # Must be a string. Default unit is seconds. Could also be a Duration, e.g.: \"2m\", \"6h\", \"1d\"\n    container:\n      image: python:alpine3.6\n      command: [\"python\", -c]\n      # fail with a 66% probability\n      args: [\"import random; import sys; exit_code = random.choice([0, 1, 1]); sys.exit(exit_code)\"]\n```\n```yaml\n\n\n# This example demonstrates the use of retries for a single container.\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: retry-on-error-\nspec:\n  entrypoint: error-container\n  templates:\n  - name: error-container\n    retryStrategy:\n      limit: \"2\"\n      retryPolicy: \"Always\"   # Retry on errors AND failures. Also available: \"OnFailure\" (default), \"OnError\", and \"OnTransientError\" (retry only on transient errors such as i/o or TLS handshake timeout. Available after v3.0.0-rc2)\n    container:\n      image: python\n      command: [\"python\", \"-c\"]\n      # fail with a 80% probability\n      args: [\"import random; import sys; print('retries: {{retries}}'); exit_code = random.choice(range(0, 5)); sys.exit(exit_code)\"]\n```\n### Synchronization\n- https://argoproj.github.io/argo-workflows/synchronization/\n```yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: my-config\ndata:\n  workflow: \"1\"  # Only one workflow can run at given time in particular namespace\n  template: \"2\"  # Two instances of template can run at a given time in particular namespace\n```\nWorkflow level:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: synchronization-wf-level-\nspec:\n  entrypoint: whalesay\n  synchronization:\n    semaphore:\n      configMapKeyRef:\n        name: my-config\n        key: workflow\n  templates:\n  - name: whalesay\n    container:\n      image: docker/whalesay:latest\n      command: [cowsay]\n      args: [\"hello world\"]\n```\nTemplate-level synchronization limits parallel execution of the template across workflows, if templates have the same synchronization reference.\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: synchronization-tmpl-level-\nspec:\n  entrypoint: synchronization-tmpl-level-example\n  templates:\n  - name: synchronization-tmpl-level-example\n    steps:\n    - - name: synchronization-acquire-lock\n        template: acquire-lock\n        arguments:\n          parameters:\n          - name: seconds\n            value: \"{{item}}\"\n        withParam: '[\"1\",\"2\",\"3\",\"4\",\"5\"]'\n\n  - name: acquire-lock\n    synchronization:\n      semaphore:\n        configMapKeyRef:\n          name: my-config\n          key: template\n    container:\n      image: alpine:latest\n      command: [sh, -c]\n      args: [\"sleep 10; echo acquired lock\"]\n```\nTwo instances of templates will be executed at a given time: even multiple steps/tasks within workflow or different workflows referring to the same template.\n### EmptyDir\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: volumes-emptydir-\nspec:\n  entrypoint: volumes-emptydir-example\n  volumes:\n  - name: workdir\n    emptyDir: {}\n\n  templates:\n  - name: volumes-emptydir-example\n    container:\n      image: debian:latest\n      command: [\"/bin/bash\", \"-c\"]\n      args: [\"\n        vol_found=`mount | grep /mnt/vol`;\n        if [[ -n $vol_found ]]; then echo \\\"Volume mounted and found\\\"; else echo \\\"Not found\\\"; fi\n      \"]\n      volumeMounts:\n      - name: workdir\n        mountPath: /mnt/vol\n```\n### Git Clone With SSH + Vault + Volume\nRemember to upload your ssh public key to Github in advance.\n\nVault configuration:\n```bash\nvault kv put internal/test/config prikey=@my/path/to/cert\n\nvault policy write myconfig - \u003c\u003cEOF\npath \"internal/data/test/config\" {\n  capabilities = [\"read\"]\n}\nEOF\n\n# grant argoadmin read permission\nvault write auth/kubernetes/role/argoadmin \\\n    bound_service_account_names=argoadmin \\\n    bound_service_account_namespaces=argo \\\n    policies=myconfig \\\n    ttl=24h\n```\n```yaml\nkind: Workflow\nmetadata:\n  generateName: input-artifact-git-\n  # namespace: argo    # uncomment this if you use kubectl apply\nspec:\n  # serviceAccountName: argoadmin    # uncomment this if you use kubectl apply\n  entrypoint: demo\n  volumeClaimTemplates:\n  - metadata:\n      name: workdir\n    spec:\n      accessModes: [ \"ReadWriteOnce\" ]\n      resources:\n        requests:\n          storage: 1Gi\n  templates:\n  - name: demo\n    steps:\n    - - name: clone\n        template: git-clone\n    - - name: print\n        template: print-message\n  - name: git-clone\n    metadata:\n      annotations:\n        vault.hashicorp.com/agent-inject: 'true'\n        vault.hashicorp.com/role: 'argoadmin'\n        vault.hashicorp.com/agent-inject-secret-myconfig: 'internal/data/test/config'\n        vault.hashicorp.com/agent-inject-template-myconfig: |\n          {{- with secret \"internal/data/test/config\" -}}\n          {{ .Data.data.prikey }}\n          {{- end -}}\n    container:\n      image: ubuntu:18.04\n      command: [\"bash\", \"-c\"]\n      args:\n        - apt-get update \u0026\u0026 apt-get install -y git;\n          mkdir /root/.ssh/ \u0026\u0026touch /root/.ssh/id_rsa \u0026\u0026 touch /root/.ssh/known_hosts;\n          cat /vault/secrets/myconfig \u003e /root/.ssh/id_rsa \u0026\u0026 chmod 600 /root/.ssh/id_rsa;\n          ssh-keyscan github.com \u003e\u003e /root/.ssh/known_hosts;\n          git clone git@github.com:minghsu0107/saga-example.git /mnt/vol;\n      volumeMounts:\n      - name: workdir\n        mountPath: /mnt/vol\n  - name: print-message\n    container:\n      image: alpine:3.14\n      command: [sh, -c]\n      args: [\"echo ls directory from volume; find /mnt/vol; ls /mnt/vol/\"]\n      volumeMounts:\n      - name: workdir\n        mountPath: /mnt/vol\n```\n```bash\nargo submit --serviceaccount argoadmin -n argo git.yaml\n\n# or use kubectl (remember to uncomment serviceaccount and namespace)\n\nkubectl create -f git.yaml\n```\n### Loops\nLoop list:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: loops-param-arg-\nspec:\n  entrypoint: loop-param-arg-example\n  arguments:\n    parameters:\n    - name: os-list\n      value: |\n        [\n          { \"image\": \"debian\", \"tag\": \"9.1\" },\n          { \"image\": \"debian\", \"tag\": \"8.9\" },\n          { \"image\": \"alpine\", \"tag\": \"3.6\" },\n          { \"image\": \"ubuntu\", \"tag\": \"17.10\" }\n        ]\n  templates:\n  - name: loop-param-arg-example\n    inputs:\n      parameters:\n      - name: os-list\n    steps:\n    - - name: test-linux\n        template: cat-os-release\n        arguments:\n          parameters:\n          - name: image\n            value: \"{{item.image}}\"\n          - name: tag\n            value: \"{{item.tag}}\"\n        withParam: \"{{inputs.parameters.os-list}}\"\n\n  - name: cat-os-release\n    inputs:\n      parameters:\n      - name: image\n      - name: tag\n    container:\n      image: \"{{inputs.parameters.image}}:{{inputs.parameters.tag}}\"\n      command: [cat]\n      args: [/etc/os-release]\n```\nWith item maps:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: loops-maps-\nspec:\n  entrypoint: loop-map-example\n  templates:\n  - name: loop-map-example\n    steps:\n    - - name: test-linux\n        template: cat-os-release\n        arguments:\n          parameters:\n          - name: image\n            value: \"{{item.image}}\"\n          - name: tag\n            value: \"{{item.tag}}\"\n        withItems:\n        - { image: 'debian', tag: '9.1' }\n        - { image: 'debian', tag: '8.9' }\n        - { image: 'alpine', tag: '3.6' }\n        - { image: 'ubuntu', tag: '17.10' }\n\n  - name: cat-os-release\n    inputs:\n      parameters:\n      - name: image\n      - name: tag\n    container:\n      image: \"{{inputs.parameters.image}}:{{inputs.parameters.tag}}\"\n      command: [cat]\n      args: [/etc/os-release]\n```\nExpanding into multiple parallel steps:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: loops-param-result-\nspec:\n  entrypoint: loop-param-result-example\n  templates:\n  - name: loop-param-result-example\n    steps:\n    - - name: generate\n        template: gen-number-list\n    - - name: sleep\n        template: sleep-n-sec\n        arguments:\n          parameters:\n          - name: seconds\n            value: \"{{item}}\"\n        withParam: \"{{steps.generate.outputs.result}}\"\n\n  - name: gen-number-list\n    script:\n      image: python:alpine3.6\n      command: [python]\n      source: |\n        import json\n        import sys\n        json.dump([i for i in range(20, 31)], sys.stdout)\n  - name: sleep-n-sec\n    inputs:\n      parameters:\n      - name: seconds\n    container:\n      image: alpine:latest\n      command: [sh, -c]\n      args: [\"echo sleeping for {{inputs.parameters.seconds}} seconds; sleep {{inputs.parameters.seconds}}; echo done\"]\n```\n### Function and Variables\nCast to string:\n```yaml=\n\"{{=string(1)}}\"\n```\nExtract data from JSON:\n```yaml=\n\"{{=jsonpath(inputs.parameters.myjson, '$.some.path')}}\"\n```\nFilter a list and turn into Json string:\n```yaml=\n\"{{=toJson(filter([1, 3], {# \u003e 1}))}}\"\n```\nMap a list:\n```yaml=\n\"{{=map([1, 2], { # * 2 })}}\"\n```\nInteger calculation for increasing memory limit on retry:\n```yaml=\nretryStrategy:\n  limit: \"{{inputs.parameters.retry_limit}}\"\n  retryPolicy: Always\n  backoff:\n    duration: 1m\n    factor: '2'\npodSpecPatch: '{\"containers\":[{\"name\":\"main\",\"resources\":{\"limits\":{\"memory\":\"{{=(sprig.int(retries) + 1) * 64}}Mi\"},\"requests\":{\"cpu\":\"{{inputs.parameters.required_cpu}}\",\"memory\":\"{{=(sprig.int(retries) + 1) * 64}}Mi\"}}}]}'\n```\nIf you are using helm chart, use the following syntax to escape from helm template:\n```yaml=\nretryStrategy:\n  limit: {{ `{{inputs.parameters.retry_limit}}` }}\n  retryPolicy: Always\n  backoff:\n    duration: 1m\n    factor: '2'\npodSpecPatch: '{\"containers\":[{\"name\":\"main\",\"resources\":{\"limits\":{\"memory\":\"{{ `{{=(sprig.int(retries) + 1) * 64}}Mi` }}\"},\"requests\":{\"cpu\":\"{{ `{{inputs.parameters.required_cpu}}` }}\",\"memory\":\"{{ `{{=(sprig.int(retries) + 1) * 64}}Mi` }}\"}}}]}'\n```\nOr:\n```yaml=\nretryStrategy:\n  limit: '{{ `{{inputs.parameters.retry_limit}}` }}'\n  retryPolicy: Always\n  backoff:\n    duration: 1m\n    factor: '2'\n{{- $reqMem := printf \"{{=(sprig.int(retries) + 1) * %v}}Mi\" .Values.crawler.resources.requests.memory }}\npodSpecPatch: '{\"containers\":[{\"name\":\"main\",\"resources\":{\"limits\":{\"memory\":\"{{  $reqMem  }}\"},\"requests\":{\"cpu\":\"{{ `{{inputs.parameters.required_cpu}}` }}\",\"memory\":\"{{ $reqMem }}\"}}}]}'\n```\n### Parallelism\n\nParallelism limits the max total parallel pods that can execute at the same time in a workflow.\n\nOnly the outer workflow `seq-step` is limited to parallelism=1:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: parallelism-nested-workflow-\nspec:\n  arguments:\n    parameters:\n    - name: seq-list\n      value: |\n        [\"a\",\"b\",\"c\",\"d\"]\n  entrypoint: A\n  templates:\n  - name: A\n    parallelism: 1\n    inputs:\n      parameters:\n      - name: seq-list\n    steps:\n    - - name: seq-step\n        template: B\n        arguments:\n          parameters:\n          - name: seq-id\n            value: \"{{item}}\"\n        withParam: \"{{inputs.parameters.seq-list}}\"\n\n  - name: B\n    inputs:\n      parameters:\n      - name: seq-id\n    steps:\n    - - name: jobs\n        template: one-job\n        arguments:\n          parameters:\n          - name: seq-id\n            value: \"{{inputs.parameters.seq-id}}\"\n        withParam: \"[1, 2]\"\n\n  - name: one-job\n    inputs:\n      parameters:\n      - name: seq-id\n    container:\n      image: alpine\n      command: ['/bin/sh', '-c']\n      args: [\"echo {{inputs.parameters.seq-id}}; sleep 30\"]\n```\nExample with vertical and horizontal scalability:\n```yaml\n# Example with vertical and horizontal scalability                                                                                                                                                                                      \n#                                                                                                                                                                                                                                                            \n# Imagine we have 'M' workers which work in parallel,                                                                                                                                                                                                        \n# each worker should performs 'N' loops sequentially                                                                                                                                                                                                         \n#                                                                                                                                                                                                                                                            \napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: parallelism-nested-\nspec:\n  arguments:\n    parameters:\n    - name: seq-list\n      value: |\n        [\"a\",\"b\",\"c\",\"d\"]\n    - name: parallel-list\n      value: |\n        [1,2,3,4]\n\n  entrypoint: parallel-worker\n  templates:\n  - name: parallel-worker\n    inputs:\n      parameters:\n      - name: seq-list\n      - name: parallel-list\n    steps:\n    - - name: parallel-worker\n        template: seq-worker\n        arguments:\n          parameters:\n          - name: seq-list\n            value: \"{{inputs.parameters.seq-list}}\"\n          - name: parallel-id\n            value: \"{{item}}\"\n        withParam: \"{{inputs.parameters.parallel-list}}\"\n\n  - name: seq-worker\n    parallelism: 1\n    inputs:\n      parameters:\n      - name: seq-list\n      - name: parallel-id\n    steps:\n    - - name: seq-step\n        template: one-job\n        arguments:\n          parameters:\n          - name: parallel-id\n            value: \"{{inputs.parameters.parallel-id}}\"\n          - name: seq-id\n            value: \"{{item}}\"\n        withParam: \"{{inputs.parameters.seq-list}}\"\n\n  - name: one-job\n    inputs:\n      parameters:\n      - name: seq-id\n      - name: parallel-id\n    container:\n      image: alpine\n      command: ['/bin/sh', '-c']\n      args: [\"echo {{inputs.parameters.parallel-id}} {{inputs.parameters.seq-id}}; sleep 10\"]\n```\n### Event and Webhook\n- https://argoproj.github.io/argo-workflows/webhooks/\n- https://argoproj.github.io/argo-workflows/events/?fbclid=IwAR2ioKfeRYdVXSpKMRVzH4dr9ZwHh1m45PO16r1xEuMCzbNXpaBJ_KamPx4\n\nNeeded role:\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: submit-workflow-template\n  namespace: argo\nrules:\n  - apiGroups:\n      - argoproj.io\n    resources:\n      - workfloweventbindings\n    verbs:\n      - list\n  - apiGroups:\n      - argoproj.io\n    resources:\n      - workflowtemplates\n    verbs:\n      - get\n  - apiGroups:\n      - argoproj.io\n    resources:\n      - workflows\n    verbs:\n      - create\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: submit-workflow\n  namespace: argo\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: submit-workflow-template\nsubjects:\n  - kind: ServiceAccount\n    name: argoadmin\n    namespace: argo\n```\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: WorkflowEventBinding\nmetadata:\n  name: event-consumer\n  namespace: argo\nspec:\n  event:\n    # metadata header name must be lowercase to match in selector\n    selector: payload.message != \"\" \u0026\u0026 metadata[\"x-argo-e2e\"] == [\"true\"] \u0026\u0026 discriminator == \"my-discriminator\"\n  submit:\n    workflowTemplateRef:\n      name: my-wf-tmple\n    arguments:\n      parameters:\n      - name: message\n        valueFrom:\n          event: payload.message\n---\napiVersion: argoproj.io/v1alpha1\nkind: WorkflowTemplate\nmetadata:\n  name: my-wf-tmple\n  namespace: argo\nspec:\n  serviceAccountName: argoadmin\n  entrypoint: main\n  templates:\n    - name: main\n      inputs:\n        parameters:\n          - name: message\n            value: \"{{workflow.parameters.message}}\"\n      container:\n        image: docker/whalesay:latest\n        command: [cowsay]\n        args: [\"{{inputs.parameters.message}}\"]\n```\n```bash\nkubectl apply -f event-template.yml\n```\nTrigger event:\n```bash\ncurl $ARGO_SERVER/api/v1/events/argo/my-discriminator \\\n    -H \"Authorization: $ARGO_TOKEN\" \\\n    -H \"X-Argo-E2E: true\" \\\n    -d '{\"message\": \"hello events\"}'\n```\nFor example:\n```bash\ncurl https://localhost:2746/api/v1/events/argo/my-discriminator \\\n    -H \"Authorization: $ARGO_TOKEN\" \\\n    -H \"X-Argo-E2E: true\" \\\n    -d '{\"message\": \"hello events\"}' \\\n    --insecure\n```\n### Cronjob\n- Use case: define cronjob workflow in a manifest repository, and sync with Kubernetes by ArgoCD.\n\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: CronWorkflow\nmetadata:\n  name: hello-world\nspec:\n  schedule: \"* * * * *\"\n  timezone: \"America/Los_Angeles\"   # Default to local machine timezone\n  startingDeadlineSeconds: 0\n  concurrencyPolicy: \"Replace\"      # Default to \"Allow\"\n  successfulJobsHistoryLimit: 4     # Default 3\n  failedJobsHistoryLimit: 4         # Default 1\n  suspend: false                    # Set to \"true\" to suspend scheduling\n  workflowSpec:                     # Same as workflow\n    entrypoint: whalesay\n    ttlStrategy:\n      secondsAfterCompletion: 300\n    templates:\n      - name: whalesay\n        container:\n          image: docker/whalesay:latest\n          command: [cowsay]\n          args: [\"🕓 hello world. Scheduled on: {{workflow.scheduledTime}}\"]\n```\n### TTL\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: gc-ttl-\nspec:\n  ttlStrategy:\n    secondsAfterCompletion: 10 # Time to live after workflow is completed, replaces ttlSecondsAfterFinished\n    secondsAfterSuccess: 5     # Time to live after workflow is successful\n    secondsAfterFailure: 5     # Time to live after workflow fails\n  entrypoint: whalesay\n  templates:\n  - name: whalesay\n    container:\n      image: docker/whalesay:latest\n      command: [cowsay]\n      args: [\"hello world\"]\n```\n### Status\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: status-reference-\nspec:\n  entrypoint: status-reference\n  templates:\n    - name: status-reference\n      steps:\n        - - name: flakey-container\n            template: flakey-container\n            continueOn:\n              failed: true\n        - - name: failed\n            template: failed\n            when: \"{{steps.flakey-container.status}} == Failed\"\n          - name: succeeded\n            template: succeeded\n            when: \"{{steps.flakey-container.status}} == Succeeded\"\n\n    - name: flakey-container\n      container:\n        image: alpine:3.6\n        command: [sh, -c]\n        args: [\"exit 1\"]\n\n    - name: failed\n      container:\n        image: alpine:3.6\n        command: [sh, -c]\n        args: [\"echo \\\"the flakey container failed\\\"\"]\n\n    - name: succeeded\n      container:\n        image: alpine:3.6\n        command: [sh, -c]\n        args: [\"echo \\\"the flakey container passed\\\"\"]\n```\n### Workflow Template\nWhen working with global parameters, you can instantiate your global variables in your `Workflow` and then directly reference them in your `WorkflowTemplate`. Below is a working example:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: WorkflowTemplate\nmetadata:\n  name: hello-world-template-global-arg\nspec:\n  serviceAccountName: argoadmin\n  templates:\n    - name: hello-world\n      container:\n        image: docker/whalesay\n        command: [cowsay]\n        args: [\"{{workflow.parameters.global-parameter}}\"]\n---\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: hello-world-wf-global-arg-\nspec:\n  serviceAccountName: argoadmin\n  entrypoint: whalesay\n  arguments:\n    parameters:\n      - name: global-parameter\n        value: hello\n  templates:\n    - name: whalesay\n      steps:\n        - - name: hello-world\n            templateRef:\n              name: hello-world-template-global-arg\n              template: hello-world\n```\nLocal parameters:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: WorkflowTemplate\nmetadata:\n  name: hello-world-template-local-arg\nspec:\n  templates:\n    - name: hello-world\n      inputs:\n        parameters:\n          - name: msg\n            value: \"hello world\"\n      container:\n        image: docker/whalesay\n        command: [cowsay]\n        args: [\"{{inputs.parameters.msg}}\"]\n---\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: hello-world-local-arg-\nspec:\n  entrypoint: whalesay\n  templates:\n    - name: whalesay\n      steps:\n        - - name: hello-world\n            templateRef:\n              name: hello-world-template-local-arg\n              template: hello-world\n            arguments:                    # You can pass in arguments as normal\n              parameters:\n              - name: msg\n                value: \"hello\"\n```\n### Create Workflow from WorkflowTemplate Spec\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: WorkflowTemplate\nmetadata:\n  name: workflow-template-submittable\nspec:\n  entrypoint: whalesay-template\n  arguments:\n    parameters:\n      - name: message\n        value: hello world\n  templates:\n    - name: whalesay-template\n      inputs:\n        parameters:\n          - name: message\n      container:\n        image: docker/whalesay\n        command: [cowsay]\n        args: [\"{{inputs.parameters.message}}\"]\n```\nHere is an example of a referring WorkflowTemplate as Workflow and using WorkflowTemplates's entrypoint and Workflow Arguments:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: workflow-template-hello-world-\nspec:\n  workflowTemplateRef:\n    name: workflow-template-submittable\n```\nHere is an example for referring WorkflowTemplate as Workflow with passing entrypoint and Workflow Arguments to WorkflowTemplate:\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: workflow-template-hello-world-\nspec:\n  entrypoint: whalesay-template\n  arguments:\n    parameters:\n      - name: message\n        value: \"from workflow\"\n  workflowTemplateRef:\n    name: workflow-template-submittable\n```\n### Slack Notification\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n  generateName: exit-handler-slack-\nspec:\n  entrypoint: say-hello\n  onExit: exit-handler\n  templates:\n  - name: say-hello\n    container:\n      image: alpine:latest\n      command: [sh, -c]\n      args: [\"echo hello\"]\n\n  - name: exit-handler\n    container:\n      image: curlimages/curl\n      command: [sh, -c]\n      args: [\n        \"curl -X POST --data-urlencode 'payload={\n          \\\"text\\\": \\\"{{workflow.name}} finished\\\",\n          \\\"blocks\\\": [\n            {\n              \\\"type\\\": \\\"section\\\",\n              \\\"text\\\": {\n                \\\"type\\\": \\\"mrkdwn\\\",\n                \\\"text\\\": \\\"Workflow {{workflow.name}} {{workflow.status}}\\\",\n              }\n            }\n          ]\n        }'\n        YOUR_WEBHOOK_URL_HERE\"\n      ]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminghsu0107%2Fargo-workflow-quickstart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminghsu0107%2Fargo-workflow-quickstart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminghsu0107%2Fargo-workflow-quickstart/lists"}