Add and Commit action
Published: 2021-03-26 15:25:34

---
title: Add and Commit action
published: true
date: 2021-03-19 09:09:39 UTC
canonical_url: https://michaelheap.com/add-and-commit-action/
series: Action Spotlight
---

[Add and Commit](https://github.com/EndBug/add-and-commit) is the second (of three!) actions that can be used to push your changes to a repo during a GitHub Actions workflow.

## What does it do?

Much like the [last spotlight post](https://michaelheap.com/git-auto-commit), today’s action is focused on adding and committing files to a repo. The README does a good job explaining how it’s different to `git-auto-commit-action`:

> This is heavily inspired by git-auto-commit-action (by Stefan Zweifel): that action automatically detects changed files and commits them. While this is useful for most situations, this doesn’t commit untracked files and can sometimes commit unintended changes (such as package-lock.json or similar, that may have happened during previous steps).

It’s also evolved from `git-auto-commit` and supports pulling changes if required before a push, removing files with `git rm` and makes features such as `signoff` an input rather than making you specify `--signoff` as a `commit_option`

## How does it work?

`add-and-commit` is implemented in TypeScript rather than `bash` and is a single 388 line file named [main.ts](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts). It uses [simple-git](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/package.json#L36) to interact with the underlying `git` repo and provides a [compiled version of the action](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/lib/index.js) that includes all dependencies.

`main.ts` itself is reasonable easy to follow:

- [Add any files](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L23-L26) that match the pattern provided in `add`
- [Remove any files](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L28-L31) if `remove` was provided
- If there are no staged files, [the action stops execution](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L159-L162)
- Otherwise [it populates](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L38-L44) `.git/config` using the `author_email` and `author_username` provided
- As GitHub Actions does a shallow clone, the action then runs `git fetch` to [get all branches](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L46)
- This isn’t documented in the README, but the action then [switches to a branch](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L49-L51) with the name specified in the `branch` input. This defaults to the branch that triggered the workflow run
- Then it [ensures that the branch is up to date](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L53-L64). You can choose `NO-PULL`, `--no-rebase`, `--no-ff` or `--rebase` depending on which strategy you prefer
- As the working branch may have changed, it then [re-adds any changed files](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L66-L68)
- Before [creating a commit](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L70-L88) using the `author_name` provided and the `--signoff` flag if the `signoff` input was set
- If the `tag` input was provided, the action also [creates a tag](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L90-L102) named after the `tag` input
- If the `push` input was [set to true](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L109-L120), it runs `git push origin <branch> --set-upstream`
- If the `push` input provided [is a string](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L120-L131) it runs `git push <input string>`
- Finally, if a [tag was created](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L133-L154) it runs `git push --tags`. This part is interesting as it [deletes a remote tag and re-pushes](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L138) when an error is encountered

There are a couple of other interesting things in the action to dig into.

One of the big questions in the Actions world is how to parse structured input. `add-and-commit` [attempts to parse inputs that can be arrays as both JSON and YAML](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L353-L380) before falling back to treating it as a simple string.

The action also [handles setting defaults in the code](https://github.com/EndBug/add-and-commit/blob/51d91f68e3700e6fd488196992e790664c51f56b/src/main.ts#L217-L221) rather than using the `default` field in `action.yml` like `git-auto-commit-action` [does](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/action.yml#L38).

## Common use cases

Automatically committing changed files can be useful in a couple of situations. The example shown in the docs is to run `eslint --fix` to fix code styling before pushing the changes back to the repo:

```yaml
name: Lint source code
on: push

jobs:
  run:
    name: Lint with ESLint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 12.x

      - name: Install dependencies
        run: npm install

      - name: Update source code
        run: eslint "src/**" --fix

      - name: Commit changes
        uses: EndBug/add-and-commit@v7
        with:
          author_name: Your Name
          author_email: mail@example.com
          message: "Your commit message"
          add: "*.js"
```

Another idea is to make sure that your `lib` folder for your action (like the one used in `add-and-commit`) is always compiled as expected on push:

```yaml
name: Automatic Compile
on: push

jobs:
  run:
    name: Compile
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 12.x

      - name: Install dependencies
        run: npm install

      - name: Compile
        run: npx ncc -o lib

      - name: Commit changes
        uses: EndBug/add-and-commit@v7
        with:
          author_name: Your Name
          author_email: mail@example.com
          message: "Your commit message"
          add: "lib"
```

## Useful links

- [GitHub Marketplace](https://github.com/marketplace/actions/add-commit)
- [GitHub Repo](https://github.com/EndBug/add-and-commit)