Git auto-commit action
Tags: github, githubactions
Published: 2021-02-07 13:06:10

---
title: Git auto-commit action
published: true
date: 2021-02-05 19:16:02 UTC
tags: github, githubactions
canonical_url: https://michaelheap.com/git-auto-commit/
series: Action Spotlight
---

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](https://github.com/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](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/action.yml#L60-L62) 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](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/index.js). `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](https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md)).

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](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L3) (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](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L5-L6). 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](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L8). If not, the `changes_detected` output is [set to false](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L23-L25) 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](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L10) and the real work starts.

In order, the following steps are executed:

- [Check out the specified branch](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L40-L54) ([defaults](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/action.yml#L14) to `github.head_ref`)
- [Add required files](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L56-L61). [By default](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/action.yml#L22) all files will be added with `.`. You can specify a pattern such as `src/*` or `*.js` with the `file_pattern` input
- [Create a commit](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L63-L79) containing the changes. The [default](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/action.yml#L27-L38) identity will commit the changes as GitHub Actions, with the change author being [set to the person that triggered the workflow run](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/action.yml#L38). You can also specify `commit_options` such as `--signoff` to add a trailer.
- If you provide a [`tagging_message`](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/action.yml#L39-L42) a tag [will be created](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L81-L91) pointing to the commit that was just created.
- Finally, the commit (and possibly a tag) will be [pushed to GitHub](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/entrypoint.sh#L93-L117). You [can specify `push_options`](https://github.com/stefanzweifel/git-auto-commit-action/blob/a6006229e0c9695d16a585acf619a3a9548b18f9/action.yml#L43-L46) to add additional flags to `git push`

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](https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#language-and-runtime). The combination of `bash` and `index.js` provides portability and speed without needing to rebuild the `git` command line tooling used.

## Useful links

- [GitHub Marketplace](https://github.com/marketplace/actions/git-auto-commit)
- [GitHub Repo](https://github.com/stefanzweifel/git-auto-commit-action)
- [Example Usage](https://github.com/stefanzweifel/git-auto-commit-action#example)