{"id":13533649,"url":"https://github.com/softprops/turnstyle","last_synced_at":"2025-05-14T08:06:55.330Z","repository":{"id":43054348,"uuid":"239345170","full_name":"softprops/turnstyle","owner":"softprops","description":"🎟️A GitHub Action for serializing workflow runs","archived":false,"fork":false,"pushed_at":"2025-05-02T15:06:24.000Z","size":1723,"stargazers_count":325,"open_issues_count":10,"forks_count":61,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-13T17:11:25.525Z","etag":null,"topics":["github-actions"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/softprops.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"ko_fi":"softprops"}},"created_at":"2020-02-09T17:33:59.000Z","updated_at":"2025-05-09T08:46:58.000Z","dependencies_parsed_at":"2024-07-18T00:08:13.809Z","dependency_job_id":"25ccac6f-f1b3-4a1d-8ca3-67dd120d130b","html_url":"https://github.com/softprops/turnstyle","commit_stats":{"total_commits":141,"total_committers":17,"mean_commits":8.294117647058824,"dds":0.6028368794326241,"last_synced_commit":"50c6cf155c4f48771284d9ac2a6ad782dab6d63c"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fturnstyle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fturnstyle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fturnstyle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fturnstyle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softprops","download_url":"https://codeload.github.com/softprops/turnstyle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254101618,"owners_count":22014909,"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","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":["github-actions"],"created_at":"2024-08-01T07:01:21.785Z","updated_at":"2025-05-14T08:06:50.320Z","avatar_url":"https://github.com/softprops.png","language":"TypeScript","funding_links":["https://ko-fi.com/softprops"],"categories":["TypeScript","Community Resources"],"sub_categories":["Deployment"],"readme":"\u003ch1 align=\"center\"\u003e\n  🎟️\n  \u003cbr/\u003e\n  turnstyle\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n   A GitHub Action for serializing workflow runs\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/softprops/turnstyle/actions\"\u003e\n\t\t\u003cimg src=\"https://github.com/softprops/turnstyle/workflows/Main/badge.svg\"/\u003e\n\t\u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n## 🤔 why bother\n\nGitHub 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.\n\nThis 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.\n\n## 🤸 Usage\n\nThe typical setup for turnstyle involves adding job step using `softprops/turnstyle@v2`.\n\n```diff\nname: Main\n\non: push\n\njobs:\n  main:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n+     - name: Turnstyle\n+       uses: softprops/turnstyle@v2\n      - name: Deploy\n        run: sleep 30\n```\n\n### Timing out\n\nTo 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.\n\nYou can bail from a run using the built-in GitHub Actions [`jobs.\u003cjob_id\u003e.timeout-minutes`](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes) setting\n\n```diff\nname: Main\n\non: push\n\njobs:\n  main:\n+   timeout-minutes: 5\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Turnstyle\n        uses: softprops/turnstyle@v2\n      - name: Deploy\n        run: sleep 30\n```\n\nYou can also limit how long you're willing to wait before moving on with `jobs.\u003cjob_id\u003e.steps.with.continue-after-seconds`\n\n```diff\nname: Main\n\non: push\n\njobs:\n  main:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Turnstyle\n        uses: softprops/turnstyle@v2\n        with:\n+         continue-after-seconds: 180\n      - name: Deploy\n        run: sleep 30\n```\n\nor before aborting the step with `jobs.\u003cjob_id\u003e.steps.with.abort-after-seconds`\n\n```diff\nname: Main\n\non: push\n\njobs:\n  main:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Turnstyle\n        uses: softprops/turnstyle@v2\n        with:\n+         abort-after-seconds: 180\n      - name: Deploy\n        run: sleep 30\n```\n\nyou can also wait on a specific job (and step) to complete in a run by using the `jobs.\u003cjob_id\u003e.steps.with.job-to-wait-for`\nand `jobs.\u003cjob_id\u003e.steps.with.step-to-wait-for` inputs. Specify the name of the job/step to wait for.\n\n```diff\nname: Main\n\non: push\n\njobs:\n  main:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Turnstyle\n        uses: softprops/turnstyle@v2\n        with:\n+         job-to-wait-for: \"main\"\n+         step-to-wait-for: \"Deploy\"\n      - name: Deploy\n        run: sleep 30\n```\n \n\nFinally, you can use the `force_continued` output to skip only a subset of steps\nby setting `continue-after-seconds` and conditioning future steps with\n`if: ! steps.\u003cstep id\u003e.outputs.force_continued`\n\n```diff\nname: Main\n\non: push\n\njobs:\n  main:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Turnstyle\n        id: turnstyle\n        uses: softprops/turnstyle@v2\n        with:\n+         continue-after-seconds: 180\n      - name: Deploy\n+       if: ! steps.turnstyle.outputs.force_continued\n        run: sleep 30\n```\n\n#### inputs\n\n| Name                     | Type    | Description                                                                                                                            |\n| ------------------------ | ------- |----------------------------------------------------------------------------------------------------------------------------------------|\n| `continue-after-seconds` | number  | Maximum number of seconds to wait before moving forward (unbound by default). Mutually exclusive with abort-after-seconds              |\n| `abort-after-seconds`    | number  | Maximum number of seconds to wait before aborting the job (unbound by default). Mutually exclusive with continue-after-seconds         |\n| `poll-interval-seconds`  | number  | Number of seconds to wait in between checks for previous run completion (defaults to 60)                                               |\n| `same-branch-only`       | boolean | Only wait on other runs from the same branch (defaults to true)                                                                        |\n| `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 |\n| `job-to-wait-for`        | string  | Name of the workflow's job to wait for (unbound by default).                                                                           |\n| `step-to-wait-for`       | string  | Name of the step to wait for (unbound by default). Required if job-to-wait-for is set.                                                 |\n\n#### outputs\n\n| Name              | Type    | Description                                                                                     |\n| ----------------- | ------- | ----------------------------------------------------------------------------------------------- |\n| `force_continued` | boolean | True if continue-after-seconds is used and the step using turnstyle continued. False otherwise. |\n\n## required permissions\n\nBecause this application leverages the `GITHUB_TOKEN` to make API requests, the\npermissions granted to the token must be sufficient to make the API requests.\nBy default, the token has wide enough permissions to allow all API requests\nmade by this action. If you are customizing your token permissions, you must\nexplicitly specify all permissions, including those that you need that would\notherwise be granted by the defaults. See [\"Permissions for the\nGITHUB_TOKEN\"](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)\nIn the GitHub Actions documentation.\n\nIf you need to specify explicit permissions for the API requests made by this\naction, the permissions required are:\n\n- `actions:read` - this permission is required for the [listWorkflowRunsForRepo](https://octokit.github.io/rest.js/v18#actions-list-workflow-runs-for-repo)\n  API request.\n\n## cost of coordination\n\nAt 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](https://github.com/features/actions#pricing-details). Waiting within one workflow run for another to complete will incur the cost of the time spent waiting.\n\nDoug Tangren (softprops) 2020\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftprops%2Fturnstyle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftprops%2Fturnstyle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftprops%2Fturnstyle/lists"}