Macros
retry
Retry flaky steps with automatic backoff.
A publish, deploy, or upload step that leans on an external service fails
intermittently — a transient 502, a rate limit, a flaky registry — and one blip
shouldn't redden the whole run. retry re-runs the same step on the same runner
up to N times with optional backoff; the first success clears it. Works with both
run: and uses: steps. When the failure is the runner itself (OOM, too few
cores), reach for fallback.retry
instead — it re-runs the step once in a fresh job on a different runs-on.
Fans out into conditional attempts, each gated on prior failure:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to production
uses: cloudflare/wrangler-action@v3
retry:
attempts: 3
delay: 10s
with:
apiToken: ${{ secrets.CF_API_TOKEN }}jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to production (attempt 1/3)
uses: cloudflare/wrangler-action@v3
id: step_deploy_to_production_attempt_1
continue-on-error: true
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
- name: Retry backoff (10s) before attempt 2/3
run: sleep 10
if: steps.step_deploy_to_production_attempt_1.outcome == 'failure'
- name: Deploy to production (attempt 2/3)
uses: cloudflare/wrangler-action@v3
id: step_deploy_to_production_attempt_2
if: steps.step_deploy_to_production_attempt_1.outcome == 'failure'
continue-on-error: true
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
- name: Retry backoff (10s) before attempt 3/3
run: sleep 10
if: steps.step_deploy_to_production_attempt_2.outcome == 'failure'
- name: Deploy to production (attempt 3/3)
uses: cloudflare/wrangler-action@v3
id: step_deploy_to_production_attempt_3
if: steps.step_deploy_to_production_attempt_2.outcome == 'failure'
with:
apiToken: ${{ secrets.CF_API_TOKEN }}jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to production
uses: cloudflare/wrangler-action@v3
retry:
attempts: 3
delay: 10s
with:
apiToken: ${{ secrets.CF_API_TOKEN }}jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to production (attempt 1/3)
uses: cloudflare/wrangler-action@v3
id: step_deploy_to_production_attempt_1
continue-on-error: true
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
- name: Retry backoff (10s) before attempt 2/3
run: sleep 10
if: steps.step_deploy_to_production_attempt_1.outcome == 'failure'
- name: Deploy to production (attempt 2/3)
uses: cloudflare/wrangler-action@v3
id: step_deploy_to_production_attempt_2
if: steps.step_deploy_to_production_attempt_1.outcome == 'failure'
continue-on-error: true
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
- name: Retry backoff (10s) before attempt 3/3
run: sleep 10
if: steps.step_deploy_to_production_attempt_2.outcome == 'failure'
- name: Deploy to production (attempt 3/3)
uses: cloudflare/wrangler-action@v3
id: step_deploy_to_production_attempt_3
if: steps.step_deploy_to_production_attempt_2.outcome == 'failure'
with:
apiToken: ${{ secrets.CF_API_TOKEN }}How it works
- Each attempt but the last gets
continue-on-error: trueso failure doesn't stop the job. - Attempt N runs only when attempt N-1 had
outcome == 'failure'. - A success at any attempt short-circuits the rest; all-fail fails the job on the final attempt.
- Each attempt gets a unique ID and auto-names as
"<step> (attempt N/max)".
Options
Prop
Type
Shorthand
retry: 3 is the same as retry: { attempts: 3 }.