A GitHub Action for serializing workflow runs
GitHub Actions is an event-oriented system. Your workflows run in response to events and are triggered independently and without coordination. In a shared repository, if two or more people merge pull requests, each will trigger workflows without regard to one another.
This can be problematic for workflows used as part of a continuous deployment process. You might want to let an in-flight deployment complete before progressing further with the next workflow. This is the usecase turnstyle action targets.
The typical setup for turnstyle involves adding job step using rpadaki/turnstyle@v1
.
name: Main
on: push
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
+ - name: Turnstyle
+ uses: rpadaki/turnstyle@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Deploy
run: sleep 30
To avoid waiting prolonged periods of time, you may wish to bail on a run or continuing a workflow run regardless of the status of the previous run.
You can bail from a run using the built-in GitHub Actions jobs.<job_id>.timeout-minutes
setting
name: Main
on: push
jobs:
main:
+ timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Turnstyle
uses: softprops/turnstyle@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Deploy
run: sleep 30
You can also limit how long you're willing to wait before moving on with jobs.<job_id>.steps.with.continue-after-seconds
name: Main
on: push
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Turnstyle
uses: softprops/turnstyle@v1
with:
+ continue-after-seconds: 180
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Deploy
run: sleep 30
or before aborting the step with jobs.<job_id>.steps.with.abort-after-seconds
name: Main
on: push
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Turnstyle
uses: softprops/turnstyle@v1
with:
+ abort-after-seconds: 180
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Deploy
run: sleep 30
Finally, you can use the force_continued
output to skip only a subset of steps
by setting continue-after-seconds
and conditioning future steps with
if: ! steps.<step id>.outputs.force_continued
name: Main
on: push
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Turnstyle
id: turnstyle
uses: softprops/turnstyle@v1
with:
+ continue-after-seconds: 180
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Deploy
+ if: ! steps.turnstyle.outputs.force_continued
run: sleep 30
Name | Type | Description |
---|---|---|
continue-after-seconds |
number | Maximum number of seconds to wait before moving forward (unbound by default). Mutually exclusive with abort-after-seconds |
abort-after-seconds |
number | Maximum number of seconds to wait before aborting the job (unbound by default). Mutually exclusive with continue-after-seconds |
poll-interval-seconds |
number | Number of seconds to wait in between checks for previous run completion (defaults to 60) |
same-branch-only |
boolean | Only wait on other runs from the same branch (defaults to true) |
initial-wait-seconds |
number | Total elapsed seconds within which period the action will refresh the list of current runs, if no runs were found in the first attempt |
Name | Type | Description |
---|---|---|
force_continued |
boolean | True if continue-after-seconds is used and the step using turnstyle continued. False otherwise. |
The following are required as step.env
keys
Name | Description |
---|---|
GITHUB_TOKEN |
GITHUB_TOKEN as provided by secrets |
At this time there is no way to coordinate between workflow runs beyond waiting. For those using private repositories, you are charged based on the time your workflow spends running. Waiting within one workflow run for another to complete will incur the cost of the time spent waiting.
Doug Tangren (softprops) 2020