237

I am planning to move our Travis CI build to GitHub Actions using Docker for our per-commit testing.

Can I reproducibly run these new GitHub Actions workflows locally? Is there a generic way to run any GitHub Actions workflow locally?

Edward Thomson
  • 74,857
  • 14
  • 158
  • 187
William Entriken
  • 37,208
  • 23
  • 149
  • 195
  • 2
    [There is](https://github.com/nektos/act) if you are still using the [deprecated](https://github.com/hashicorp/terraform-github-actions/issues/40) HCL syntax for actions and haven't graduated to the new YAML style. I have yet to see anything being done to support the new yaml style workflows – smac89 Dec 09 '19 at 05:47
  • 1
    there is a lot of interest for `nejtos/act` to support YAML syntax, see my answer below with links to the issues it's being discussed. – Zia Jan 31 '20 at 00:19
  • 2
    maybe self-hosted runners can help https://github.com/actions/runner – UselesssCat Jul 09 '21 at 01:44

9 Answers9

199

There are tools like the already-mentioned act, but they are not perfect. You are not alone with this issue. Similar problems are:

  • how to test Jenkins builds locally
  • how to test Circle CI builds locally
  • how to test XXXX builds locally

And my solution for these problems is:

  • avoid functionalities provided by your CI tools (GitHub Actions, Gitlab CI, etc)
  • write as much as possible in CI-agnostic way (BASH scripts, PowerShell scripts, Gradle scripts, NPM scripts, Dockerfiles, Ansible scripts - anything you know)
  • invoke those scripts from your CI tool. In GitHub actions: run: your command to run

Update 2022; Bit-bucket's Pipelines support running locally, which means 100% free use-hours, with the cost of buying own PC/Mac (if you want permanent server).

Top-Master
  • 7,611
  • 5
  • 39
  • 71
iirekm
  • 8,890
  • 5
  • 36
  • 46
  • 39
    Actually gitlab has a cli tool to test your workflows: `gitlab-runner exec docker my-job` – Zia Jan 31 '20 at 00:12
  • 22
    Great answer! but unfortunately this doesn't help much when you are testing things like uploading and downloading artifacts to github releases. – dmedine Aug 19 '20 at 05:43
  • Maybe github api or github cli can do that? Unfortunately my method works only for some 95% of actions. Things like collecting test results and coverage from xmls generated by tools, and maybe your problem, can only be done natively by GHA / Jenkins, etc – iirekm Aug 20 '20 at 06:19
  • 3
    Circle CI also allows you to run locally: https://circleci.com/docs/2.0/local-cli/ – Mike Pennington Sep 21 '20 at 15:50
  • https://github.com/firecow/gitlab-ci-local I've made this project. – Firecow Dec 05 '20 at 16:40
  • 4
    "CI-agnostic way" brings on caching challenges when using each specific CI caching capabilities – luismartingil Oct 04 '21 at 11:05
  • 1
    Why? There are at least 3 approaches to caching in CI: 1. For example with Gradle you can just tell CI to cache ~/.gradle and ./**/build/** directories, with nodejs it'll be ./**/node_modules/**. Probably all CI tools support caching of file masks (by zipping them and uploading) - unfortunately it's slow 2. Create your own persistent gitlab/gitbub actions runner per project. All files will be in local directory. Caching is fast and easy. 3. Gradle can use Gradle Enterprise Server to download - upload contents of build dirs – iirekm Oct 06 '21 at 07:33
  • 5
    That's exactly what I have been doing for years now. The benefit of being in control and not relying on proprietary CI tooling far outweighs the benefit of being able to see little circles marked with checkmarks for each stage completed. CI tool vendors should provide hooks for our scripts to use to indicate stages completed. CI tool vendors should handle caching transparently to us; it is their problem, not ours. – Mike Nakis May 24 '22 at 11:52
65

One way to test Github actions is to create a private repo, and iterate the actions conf there. So you can avoid polluting the actual repo with broken commits.

I know, this is not a direct answer to the question - this is not a local way. But this didn’t occur to me at first and I think this could be enough for many use cases.

juhoautio
  • 1,541
  • 1
  • 22
  • 23
  • This is a handful when working with massive, multi-repo projects. Wish there was a better alternative but unfortunately this is the only guaranteed mirror functionality for testing. – m4heshd Aug 23 '21 at 07:32
  • 75
    Another possibility is creating a new branch in your repo, pushing changes to that branch until you get the action working, and then squash into a single commit and merge into main. – Jordan Mitchell Barrett Nov 07 '21 at 12:28
  • 2
    @JordanMitchellBarrett This sadly doesn't work when adding *new* workflows. Sometimes, the workflow YAML files have to exist on your mainline/default branch for them to show up in the actions UI. – void.pointer May 10 '23 at 13:20
  • 1
    @void.pointer This is true! What I do in this case is, I create a minimal new workflow in main/master so it shows up under GitHub Actions. And then after this, I create a new branch and continue my development and testing of the workflow til it works fully as I want it to. – John May 17 '23 at 09:50
  • @JordanMitchellBarrett this should be an answer – nocibambi Jul 05 '23 at 12:36
45

You can use nektos/act which supports yaml syntax since 0.2.0 (prerelease).

Check out their latest release.

Webber
  • 4,672
  • 4
  • 29
  • 38
  • 1
    but it does not work on .net/windows projects :( – Daniel Williams Nov 02 '22 at 20:45
  • @DanielWilliams any details on what doesn't work exactly? Is it act related? – Webber Nov 02 '22 at 20:50
  • I keep getting: "{Skipping unsupported platform -- Try running with `-P windows-latest=...` " But nothing is accepted as arguments to -P I tried this: -P ubuntu-latest=node:16-buster-slim but same error every time – Daniel Williams Nov 04 '22 at 12:15
  • @DanielWilliams would you mind reporting that? https://github.com/nektos/act/issues – Webber Nov 05 '22 at 12:03
  • 1
    Thanks, this is helpful. I noticed some differences between execution in GitHub Actions and act when running a python script. I noticed a script ran under GitHub Actions seem to be cached implicitly. This is probably more of GitHub Actions issue than anything, but I was able to catch this behavior thanks to nektos/act. – Omar Khazamov Nov 30 '22 at 18:16
21

I'm assuming that you want to run the action locally because it is failing, and you want to debug it. If so, another alternative (which doesn't require running locally) is to use action-tmate to SSH into the machine running your action. From there, you can view logs, run commands, etc to work out what the problem is.

To get started:

  1. In your workflow yaml file, after the step that is failing (or at the end), put a new step as follows:
    - name: Setup tmate session
      if: success() || failure()
      uses: mxschmitt/action-tmate@v3
  1. Push the changes to GitHub and rerun the action.

  2. Wait for it to fail again - this time, instead of stopping the workflow, a tmate session will be opened, and the SSH details will be printed in the workflow console.

  3. Connect via SSH from your own machine, and now you have full access to the runner machine.

13

your best bet is https://github.com/nektos/act however (prior to 0.2.0) it doesn't support yaml syntax yet, though there is a lot of interest aka: https://github.com/nektos/act/issues/80 https://github.com/nektos/act/issues/76 and https://github.com/nektos/act/issues/74

Gitlab has gitlab-runner exec docker job-name but that's Gitlab :)

WEBjuju
  • 5,797
  • 4
  • 27
  • 36
Zia
  • 2,735
  • 3
  • 30
  • 27
5

In my case ACT was failing even if the GitHub CI was passing so I have found this:

https://github.com/actions/runner

official github action runner (can be self-hosted). Follow instructions in readme.

It is a little different than the ACT but allows for example to pair repo CI to local runner (can use cuda for example)

Adam Krawczyk
  • 71
  • 1
  • 5
2

To add on top of what's being said by @iirekm and @riQQ, in order to stay CI-agnostic and have some orchestration features, you could abstract your steps with Task and then call your tasks from your Github Actions or any other CI/CD. That way you also get the benefit of being able run everything locally.

crazy-matt
  • 33
  • 1
  • 4
1

with the use of docker containers, this tool called act, can be found here, https://github.com/nektos/act You can run all your github actions locally inside a docker container. NB: act builds all necessary containers for actions to run. all you do is follow the documentation on how to use the tool

1

Another option is to put all the work into makefiles, and using GitHub Action(s) to call make.

That way, the jobs can be triggered to run locally via the make command, or remotely via a GitHub Action (also using the make command, but inside a GitHub Action).

I came across this approach mentioned here (one of the top comments on this thread).

stevec
  • 41,291
  • 27
  • 223
  • 311
  • This isn't really the same thing, though. This will cause all actions to run in the context of one container/shell process, which is fine for singular services, but once you add database+cache+backend+frontend, it doesn't work as well – OneCricketeer May 27 '23 at 04:50