{"id":20564542,"url":"https://github.com/tarantool/job-rerunner","last_synced_at":"2025-09-25T22:31:45.916Z","repository":{"id":50676785,"uuid":"519354206","full_name":"tarantool/job-rerunner","owner":"tarantool","description":"Service which can re-run failed GitHub Actions jobs","archived":false,"fork":false,"pushed_at":"2023-06-07T11:51:18.000Z","size":16,"stargazers_count":3,"open_issues_count":3,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-12-22T18:05:09.253Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","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/tarantool.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-29T21:30:56.000Z","updated_at":"2023-05-31T09:53:08.000Z","dependencies_parsed_at":"2024-11-16T04:37:35.581Z","dependency_job_id":null,"html_url":"https://github.com/tarantool/job-rerunner","commit_stats":null,"previous_names":["tarantool/job-rerunner"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fjob-rerunner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fjob-rerunner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fjob-rerunner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fjob-rerunner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tarantool","download_url":"https://codeload.github.com/tarantool/job-rerunner/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234260959,"owners_count":18804468,"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":[],"created_at":"2024-11-16T04:27:37.545Z","updated_at":"2025-09-25T22:31:45.607Z","avatar_url":"https://github.com/tarantool.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tarantool Workflow Re-runner\n\nThis service is written in Lua and runs on [Tarantool](https://tarantool.io).\n\nIt receives webhooks from all completed workflows in a certain GitHub repository.\nIf a webhook came with `check_run.conclusion == failure` in the \n[payload](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#check_run), \nthe service calls GitHub API to re-run failed jobs in the workflow.\n\n## Adding repositories\n\nTo enable restarting workflows in a repository:\n\n1. Add a new webhook in the repository.\n   You should have \"Admin\" permissions in the repository to do so.\n   \n   * Set \"Payload URL\" to the service endpoint.\n   * Select \"application/json\" in the \"Content type\" dropdown.\n   * Pick \"Let me select individual events\", then check \"Workflow jobs\" in the bottom of the page.\n   \n   \n2. Add the bot user to the repository with \"Write\" permissions.\n   For repos in the [tarantool organization](https://github.com/tarantool),\n   it's the [@TarantoolBot](https://github.com/TarantoolBot).\n   \nThe service will now restart all failed workflows in this repository up to three times.\n\n## Deployment\n\nThe app is deployed in [Dokku](https://dokku.com) using the \n[dummy buildpack](https://github.com/maximkulkin/heroku-buildpack-dummy).\n\nDokku must have [dokku-apt](https://github.com/dokku-community/dokku-apt)\nplugin enabled to install `apt` dependencies in `apt-*` files.\n\nProvide the SSH key for access to Dokku in the `SSH_PRIVATE_KEY` secret.\n\n`Procfile` contains the command for running the main process of the application.\n\n## Environment variables\n\n| Variable        | Default | Meaning                                                                       |\n|-----------------|---------|-------------------------------------------------------------------------------|\n| RUN_ATTEMPTS    | 4       | Number of attempts to run a specific workflow job.                            |\n| REPO_BRANCHES   | master  | Branches that require automatic restart of workflow jobs.                     |\n| GITHUB_TOKEN    |         | Access token for authentication to GitHub when using the GitHub API.          |\n| GITHUB_SIGN_KEY |         | Secret token for generating a hash function for the checking GitHub requests. |\n\n## Updating GitHub token and GitHub Sign Key\n\nTo update the token or change the user which will restart workflows:\n\n1. [Issue a new token](https://github.com/settings/tokens/new) with scopes `repo` and `workflow`.\n2. Add the token to the service config in Dokku:\n\n    ```console\n    $ ssh user@dokku-machine\n    $ sudo su\n    # dokku config job-re-runner\n    BUILDPACK_URL:            https://github.com/maximkulkin/heroku-buildpack-dummy.git\n    DOKKU_APP_RESTORE:        1\n    DOKKU_APP_TYPE:           herokuish\n    DOKKU_LETSENCRYPT_EMAIL:  admin@org\n    DOKKU_PROXY_PORT:         80\n    DOKKU_PROXY_PORT_MAP:     http:80:5000 https:443:5000\n    DOKKU_PROXY_SSL_PORT:     443\n    GITHUB_TOKEN:             \u003cold_token_value\u003e\n    GITHUB_SIGN_KEY:          \u003cold_github_signature\u003e\n    GIT_REV:                  e4da2ec3daf9366236da98b5ba06ecbe4d645365\n\n    # dokku config:set job-re-runner GITHUB_TOKEN=\u003cvalue\u003e\n    -----\u003e Setting config vars\n       GITHUB_TOKEN:  \u003cvalue\u003e\n    -----\u003e Restarting app job-re-runner\n    ...\n\n    # dokku config:set job-re-runner GITHUB_SIGN_KEY=\u003cvalue\u003e\n    -----\u003e Setting config vars\n       GITHUB_SIGN_KEY:  \u003cvalue\u003e\n    -----\u003e Restarting app job-re-runner\n    ...\n    ```\n    \n    Dokku will now deploy a new service instance with the new configuration.\n    There shouldn't be any downtime in the deployment.\n    \n## Logging\n\nTo read service logs, SSH to the Dokku machine:\n\n```console\n$ ssh user@dokku-machine\n$ sudo su\n# dokku logs job-re-runner --tail\n```\n\n## Payload example\n\n\u003cdetails\u003e\n\u003csummary\u003e\n\u003ca href=\"https://github.com/tarantool/tarantool/runs/8039369388?check_suite_focus=true\"\u003eJob `osx_11_lto`\u003c/a\u003e\nfailed:\n\u003c/summary\u003e\n\n```json\n{\n   \"workflow_job\": {\n      \"head_sha\": \"0d5ec357fb8684bd26a74f0b8b3a5020768688eb\",\n      \"id\": 11786061154,\n      \"head_branch\": \"master\",\n      \"node_id\": \"CR_kwDOH2Isjs8AAAACvoEFYg\",\n      \"workflow_name\": \"Deploy branch\",\n      \"url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/actions\\/jobs\\/11786061154\",\n      \"run_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/actions\\/runs\\/4341897961\",\n      \"run_id\": 4341897961,\n      \"status\": \"in_progress\",\n      \"conclusion\": null,\n      \"runner_group_id\": 1,\n      \"completed_at\": null,\n      \"runner_name\": \"ghacts-shared-1-2-n1\",\n      \"created_at\": \"2023-03-06T09:30:16Z\",\n      \"steps\": [\n         {\n            \"number\": 1,\n            \"conclusion\": null,\n            \"status\": \"in_progress\",\n            \"completed_at\": null,\n            \"name\": \"Set up job\",\n            \"started_at\": \"2023-03-06T09:30:19.000Z\"\n         }\n      ],\n      \"run_attempt\": 1,\n      \"runner_id\": 232,\n      \"check_run_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/check-runs\\/11786061154\",\n      \"labels\": [\n         \"self-hosted\",\n         \"Linux\",\n         \"flavor-1-2\"\n      ],\n      \"runner_group_name\": \"Default\",\n      \"started_at\": \"2023-03-06T09:30:20Z\",\n      \"name\": \"other-job (5, 1)\",\n      \"html_url\": \"https:\\/\\/github.com\\/tarantool\\/devx-team-sandbox\\/actions\\/runs\\/4341897961\\/jobs\\/7582057694\"\n   },\n   \"sender\": {\n      \"login\": \"lastoCHka42\",\n      \"events_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/events{\\/privacy}\",\n      \"gists_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/gists{\\/gist_id}\",\n      \"repos_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/repos\",\n      \"node_id\": \"MDQ6VXNlcjg4NzQ2Nzkw\",\n      \"gravatar_id\": \"\",\n      \"received_events_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/received_events\",\n      \"starred_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/starred{\\/owner}{\\/repo}\",\n      \"avatar_url\": \"https:\\/\\/avatars.githubusercontent.com\\/u\\/88746790?v=4\",\n      \"site_admin\": false,\n      \"type\": \"User\",\n      \"html_url\": \"https:\\/\\/github.com\\/lastoCHka42\",\n      \"id\": 88746790,\n      \"followers_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/followers\",\n      \"subscriptions_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/subscriptions\",\n      \"following_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/following{\\/other_user}\",\n      \"url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\",\n      \"organizations_url\": \"https:\\/\\/api.github.com\\/users\\/lastoCHka42\\/orgs\"\n   },\n   \"action\": \"in_progress\",\n   \"organization\": {\n      \"members_url\": \"https:\\/\\/api.github.com\\/orgs\\/tarantool\\/members{\\/member}\",\n      \"login\": \"tarantool\",\n      \"issues_url\": \"https:\\/\\/api.github.com\\/orgs\\/tarantool\\/issues\",\n      \"events_url\": \"https:\\/\\/api.github.com\\/orgs\\/tarantool\\/events\",\n      \"repos_url\": \"https:\\/\\/api.github.com\\/orgs\\/tarantool\\/repos\",\n      \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjIzNDQ5MTk=\",\n      \"public_members_url\": \"https:\\/\\/api.github.com\\/orgs\\/tarantool\\/public_members{\\/member}\",\n      \"url\": \"https:\\/\\/api.github.com\\/orgs\\/tarantool\",\n      \"hooks_url\": \"https:\\/\\/api.github.com\\/orgs\\/tarantool\\/hooks\",\n      \"avatar_url\": \"https:\\/\\/avatars.githubusercontent.com\\/u\\/2344919?v=4\",\n      \"id\": 2344919,\n      \"description\": \"In-memory computing platform with flexible data schema.\"\n   },\n   \"repository\": {\n      \"disabled\": false,\n      \"subscribers_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/subscribers\",\n      \"private\": false,\n      \"notifications_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/notifications{?since,all,participating}\",\n      \"tags_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/tags\",\n      \"pushed_at\": \"2023-02-14T12:18:16Z\",\n      \"description\": \"Tests and experiments in the DevX team\",\n      \"license\": null,\n      \"deployments_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/deployments\",\n      \"keys_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/keys{\\/key_id}\",\n      \"comments_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/comments{\\/number}\",\n      \"language\": null,\n      \"has_wiki\": false,\n      \"releases_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/releases{\\/id}\",\n      \"has_downloads\": true,\n      \"forks_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/forks\",\n      \"has_pages\": false,\n      \"watchers_count\": 0,\n      \"downloads_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/downloads\",\n      \"size\": 5,\n      \"assignees_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/assignees{\\/user}\",\n      \"issues_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/issues{\\/number}\",\n      \"commits_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/commits{\\/sha}\",\n      \"clone_url\": \"https:\\/\\/github.com\\/tarantool\\/devx-team-sandbox.git\",\n      \"owner\": {\n         \"login\": \"tarantool\",\n         \"events_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/events{\\/privacy}\",\n         \"gists_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/gists{\\/gist_id}\",\n         \"repos_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/repos\",\n         \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjIzNDQ5MTk=\",\n         \"gravatar_id\": \"\",\n         \"received_events_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/received_events\",\n         \"starred_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/starred{\\/owner}{\\/repo}\",\n         \"avatar_url\": \"https:\\/\\/avatars.githubusercontent.com\\/u\\/2344919?v=4\",\n         \"site_admin\": false,\n         \"type\": \"Organization\",\n         \"html_url\": \"https:\\/\\/github.com\\/tarantool\",\n         \"id\": 2344919,\n         \"followers_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/followers\",\n         \"subscriptions_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/subscriptions\",\n         \"following_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/following{\\/other_user}\",\n         \"url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\",\n         \"organizations_url\": \"https:\\/\\/api.github.com\\/users\\/tarantool\\/orgs\"\n      },\n      \"languages_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/languages\",\n      \"hooks_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/hooks\",\n      \"git_commits_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/git\\/commits{\\/sha}\",\n      \"name\": \"devx-team-sandbox\",\n      \"teams_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/teams\",\n      \"updated_at\": \"2022-10-05T11:24:55Z\",\n      \"issue_events_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/issues\\/events{\\/number}\",\n      \"default_branch\": \"master\",\n      \"events_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/events\",\n      \"homepage\": null,\n      \"node_id\": \"R_kgDOH2Isjg\",\n      \"pulls_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/pulls{\\/number}\",\n      \"visibility\": \"public\",\n      \"url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\",\n      \"statuses_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/statuses\\/{sha}\",\n      \"git_url\": \"git:\\/\\/github.com\\/tarantool\\/devx-team-sandbox.git\",\n      \"branches_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/branches{\\/branch}\",\n      \"issue_comment_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/issues\\/comments{\\/number}\",\n      \"created_at\": \"2022-08-19T08:39:08Z\",\n      \"labels_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/labels{\\/name}\",\n      \"trees_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/git\\/trees{\\/sha}\",\n      \"web_commit_signoff_required\": false,\n      \"archived\": false,\n      \"allow_forking\": true,\n      \"topics\": [\n      ],\n      \"id\": 526527630,\n      \"watchers\": 0,\n      \"open_issues\": 1,\n      \"has_issues\": true,\n      \"forks\": 0,\n      \"contributors_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/contributors\",\n      \"mirror_url\": null,\n      \"open_issues_count\": 1,\n      \"is_template\": false,\n      \"milestones_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/milestones{\\/number}\",\n      \"git_tags_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/git\\/tags{\\/sha}\",\n      \"subscription_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/subscription\",\n      \"forks_count\": 0,\n      \"git_refs_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/git\\/refs{\\/sha}\",\n      \"html_url\": \"https:\\/\\/github.com\\/tarantool\\/devx-team-sandbox\",\n      \"svn_url\": \"https:\\/\\/github.com\\/tarantool\\/devx-team-sandbox\",\n      \"contents_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/contents\\/{+path}\",\n      \"merges_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/merges\",\n      \"stargazers_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/stargazers\",\n      \"full_name\": \"tarantool\\/devx-team-sandbox\",\n      \"archive_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/{archive_format}{\\/ref}\",\n      \"fork\": false,\n      \"collaborators_url\": \"https:\\/\\/api.github.com\\/repos\\/tarantool\\/devx-team-sandbox\\/collaborators{\\/collaborator}\",\n      \"ssh_url\": \"git@github.com:tarantool\\/devx-team-sandbox.git\",\n      \"stargazers_count\": 0,\n      \"blobs_url\": \"https:\\/\\/api.github.com\\/repos\\/\"\n   }\n}\n```\n\n\u003c/details\u003e\n\n## Status codes\nJob rerunner returns some status code while working on payload from GitHub.\n\n|     | Result     | Meaning                                                                                           |\n|-----|------------|---------------------------------------------------------------------------------------------------|\n| 204 | No Content | Got empty payload, overall run attempts more than allowed, or user in `NO_RETRY_LIST` No action.  |\n| 200 | OK         | Final job was completed, but no action is required.                                               |\n| 201 | Created    | Final job was completed, restarting the workflow.                                                 |\n| 202 | Accepted   | Recorded the queued or completed jobs and waiting for results.                                    |\n| 403 | Forbidden  | Request headers must contain `X-Hub-Signature-256` with correct value.                            |\n| 404 | Error      | Job action is 'completed', but there's no previous record about it.                               |\n\n## Excluding usernames from retrying\nRerunner will not restart workflows initiated by GitHub users,\nspecified in the environment variable `NO_RETRY_LIST`:\nNO_RETRY_LIST=username1,username2\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftarantool%2Fjob-rerunner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftarantool%2Fjob-rerunner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftarantool%2Fjob-rerunner/lists"}