Git auto-commit action

05 Feb 2021 in Tech

February’s Action Spotlight theme is all about committing changes that you’ve made back to your GitHub repo, starting with stefanzweifel/git-auto-commit-action.

What does it do?

The GitHub Action for committing files for the 80% use case.

By default, any changes made to the workspace when running a GitHub Action are discarded when the job ends. This means that whilst Actions is great for running tools such as eslint to check your code style, if you wanted to use eslint --fix to automatically fix any violations and push those changes to a pull request you’re out of luck.

Until now, that is. git-auto-commit-action will automatically add, commit and push any created or changed files back to your repo automatically.

How does it work?

Taking a look at the repo, the action is defined as a JavaScript action but has an entrypoint.sh script. This seems odd as shell scripts are usually run using the Docker runtime.

Looking at index.js, things become a little clearer. git-auto-commit-action uses a shim to trick Actions into running a shell script directly on the runner machine rather than building a Docker container. This works as the runner machines have bash preinstalled (here’s the list of software for Ubuntu 20.04).

The bash script is well architected, with well named functions and good debugging information. It also uses set -eu to make the script very brittle (this is a good thing!) ensuring that it fails fast. The -e flag will automatically stop execution of the script if any command executed fails, and the -u flag treats missing variables as an error when trying to use them. These two options combined mean that if any variables are missing, the script will exit instantly.

The _main function is our entrypoint into the script. The first thing it does is change to the specified directory. By default the repository input is . which means that the script will run in the current directory, which is the repository root.

Any action inputs are available as variables prefixed with INPUT_ in GitHub Actions

Next, it checks if there have been any changes made. If not, the changes_detected output is set to false and the script exits. You can disable this check by setting the skip_dirty_check input to true.

If changes were detected, changes_detected is set to true and the real work starts.

In order, the following steps are executed:

The default behaviour is the most useful to the majority of people, but having the configuration options available are useful. Imagine setting commit_options to --amend --no-edit and push_options to --force to automatically fix code style issues in the same commit rather than adding a new one, or passing repository: src to only commit changes in the src directory.

Writing the action in bash allows stefanzweifel to make the most of the git command line and not reimplement the world in JavaScript for a relatively simple action. They use an index.js shim which adds support for Windows and MacOS runners (in addition to making the action run fast) as Windows and MacOS don’t support Docker actions, but they do support Bash. The combination of bash and index.js provides portability and speed without needing to rebuild the git command line tooling used.