1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2958],{57820:(e,s,n)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/after",function(){return n(84535)}])},84535:(e,s,n)=>{"use strict";n.r(s),n.d(s,{__N_SSG:()=>a,default:()=>i});var r=n(37876),t=n(91668);function o(e){let s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.R)(),...e.components},{WarningNote:n}=s;return n||function(e,s){throw Error("Expected "+(s?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("WarningNote",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h1,{id:"after",children:"After"}),"\n",(0,r.jsxs)(s.p,{children:["When you specify dependencies using the ",(0,r.jsx)(s.a,{href:"/use",children:"use keyword"}),", the task inherits the file system contents and environment variables of its dependencies."]}),"\n",(0,r.jsxs)(s.p,{children:["If you want to run tasks after other tasks without inheriting the output of the dependencies, you should use the ",(0,r.jsx)(s.code,{children:"after"})," keyword instead."]}),"\n",(0,r.jsx)(s.p,{children:"A few common scenarios include:"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Continuous Deployment workflows, where tasks have side effects of modifying external resources and need to run in a specific order"}),"\n",(0,r.jsx)(s.li,{children:"ETL workflows where state is stored externally and tasks need to run in a specific order"}),"\n",(0,r.jsx)(s.li,{children:"Optimizing build minutes, where you may want to make sure some tasks succeed before running others"}),"\n"]}),"\n",(0,r.jsx)(s.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(s.pre,{language:"yaml",code:"tasks:\n - key: one\n run: echo this is task one\n\n - key: two\n run: echo this is task two\n\n - key: three\n after: [one, two]\n run: echo task three waits for one and two to finish before running\n",children:(0,r.jsx)(s.code,{className:"language-yaml",children:'<span><span style="color: var(--shiki-token-keyword)">tasks</span><span style="color: var(--shiki-token-keyword)">:</span></span>\n<span><span style="color: var(--shiki-color-text)"> - </span><span style="color: var(--shiki-token-keyword)">key</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">one</span></span>\n<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">run</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">echo this is task one</span></span>\n<span></span>\n<span><span style="color: var(--shiki-color-text)"> - </span><span style="color: var(--shiki-token-keyword)">key</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">two</span></span>\n<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">run</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">echo this is task two</span></span>\n<span></span>\n<span><span style="color: var(--shiki-color-text)"> - </span><span style="color: var(--shiki-token-keyword)">key</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">three</span></span>\n<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">after</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string)">one</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">two</span><span style="color: var(--shiki-color-text)">]</span></span>\n<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">run</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">echo task three waits for one and two to finish before running</span></span>\n<span></span>'})}
1),"\n",(0,r.jsx)(s.h2,{id:"running-tasks-after-other-tasks-fail",children:"Running tasks after other tasks fail"}),"\n",(0,r.jsxs)(s.p,{children:["By default, using ",(0,r.jsx)(s.code,{children:"after"})," means that the task will only run if every task listed in ",(0,r.jsx)(s.code,{children:"after"})," succeeds.\nHowever, you may want to run some tasks after others fail.\nTo do this, you can configure ",(0,r.jsx)(s.code,{children:"after"})," using an expression instead of an array."]}),"\n",(0,r.jsx)(s.pre,{language:"yaml",code:"tasks:\n - key: one\n run: exit 1\n\n - key: if-one-fails\n after: ${{ one.failed }}\n run: echo task one failed!\n",children:(0,r.jsx)(s.code,{className:"language-yaml",children:'<span><span style="color: var(--shiki-token-keyword)">tasks</span><span style="color: var(--shiki-token-keyword)">:</span></span>\n<span><span style="color: var(--shiki-color-text)"> - </span><span style="color: var(--shiki-token-keyword)">key</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">one</span></span>\n<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">run</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">exit 1</span></span>\n<span></span>\n<span><span style="color: var(--shiki-color-text)"> - </span><span style="color: var(--shiki-token-keyword)">key</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">if-one-fails</span></span>\n<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">after</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">${{ one.failed }}</span></span>\n<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">run</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">echo task one failed!</span></span>\n<span></span>'})}),"\n",(0,r.jsxs)(s.p,{children:["You can use ",(0,r.jsx)(s.code,{children:"&&"})," and ",(0,r.jsx)(s.code,{children:"||"})," operators to list multiple tasks within the expression.\nFor more details, see the ",(0,r.jsx)(s.a,{href:"/expressions",children:"documentation on expressions"}),"."]}),"\n",(0,r.jsxs)(n,{children:[(0,r.jsxs)(s.p,{children:["All tasks are cancelled when the entire run is cancelled.\nIn the previous example, ",(0,r.jsx)(s.code,{children:"if-one-fails"})," could be cancelled and not run, even if ",(0,r.jsx)(s.code,{children:"${{ one.failed }}"})," is ",(0,r.jsx)(s.code,{children:"true"}),"."]}),(0,r.jsxs)(s.p,{children:["If you want to run a task after failure to clean up an external resource, you may want to consider running a periodic task via a ",(0,r.jsx)(s.a,{href:"/cron-schedules",children:"cron trigger"})," to look for any resources which were missed."]})]}),"\n",(0,r.jsx)(s.h2,{id:"status-attributes",children:"Status attributes"}),"\n",(0,r.jsxs)(s.p,{children:["To control the ",(0,r.jsx)(s.code,{children:"after"})," conditions, the following attributes are available on tasks within expressions."]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Result status attributes"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"attribute"}),(0,r.jsx)(s.th,{children:"description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"succeeded"})}),(0,r.jsx)(s.td,{children:"The task was successful. It may have executed or been a cache hit."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"failed"})}),(0,r.jsx)(s.td,{children:"The task failed. It may have executed or failed for another reason such as being cancelled."})]})]})]}),"\n",(0,r.jsxs)(s.p,{children:["Note that skipped tasks, which you can check via ",(0,r.jsx)(s.code,{children:".skipped"}),", will return ",(0,r.jsx)(s.code,{children:"false"})," for both ",(0,r.jsx)(s.code,{children:"succeeded"})," and ",(0,r.jsx)(s.code,{children:"failed"}),"."]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Execution status attributes"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"attribute"}),(0,r.jsx)(s.th,{children:"description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"finished"})}),(0,r.jsxs)(s.td,{children:["The task finished running. Notably, ",(0,r.jsx)(s.code,{children:".finished"})," is false for tasks that are ",(0,r.jsx)(s.code,{children:".aborted"})," or ",(0,r.jsx)(s.code,{children:".skipped"}),"."]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"aborted"})}),(0,r.jsx)(s.td,{children:"The task was aborted either before or after it started running."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"cancelled"})}),(0,r.jsxs)(s.td,{children:["The task was ",(0,r.jsx)(s.code,{children:"aborted"})," due to being cancelled. Most of the time, you'll want to check ",(0,r.jsx)(s.code,{children:".aborted"})," instead of ",(0,r.jsx)(s.code,{children:".cancelled"}),"."]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"skipped"})}),(0,r.jsxs)(s.td,{children:["The task was skipped. These tasks will return ",(0,r.jsx)(s.code,{children:"false"})," for both ",(0,r.jsx)(s.code,{children:".succeeded"})," and ",(0,r.jsx)(s.code,{children:".failed"}),"."]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"cache-hit"})}),(0,r.jsx)(s.td,{children:"The task was a cache hit."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"timed-out"})}),(0,r.jsxs)(s.td,{children:["The task was ",(0,r.jsx)(s.code,{children:"aborted"})," due to timing out."]})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"after-success-or-failure",children:"After success or failure"}),"\n",(0,r.jsx)(s.p,{children:"If you want to run a task after another task, regardless of whether that task succeeds or fails, then you currently must check for both states:"}),"\n",(0,r.jsx)(s.pre,{code:"${{ (example-task.succeeded || example-task.failed) }}\n",children:(0,r.jsx)(s.code,{children:"${{ (example-task.succeeded || example-task.failed) }}\n"})}),"\n",(0,r.jsx)(s.h3,{id:"failed-after-running",children:"Failed after running"}),"\n",(0,r.jsx)(s.p,{children:"If you want to run a task after another task fails, but only if that task actually executed (e.g. it finished running and then exited
1with a non-zero exit status), then you can check:"}),"\n",(0,r.jsx)(s.pre,{code:"${{ (example-task.failed && example-task.finished) }}\n",children:(0,r.jsx)(s.code,{children:"${{ (example-task.failed && example-task.finished) }}\n"})})]})}var a=!0;function i(e={}){let{wrapper:s}={...(0,t.R)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}}},e=>{e.O(0,[636,6593,8792],()=>e(e.s=57820)),_N_E=e.O()}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.