A workflow to generate Git patches for auto-fixable issues
Tags: actionshackathon21, github, opensource
Published: 2021-12-06 15:08:14

---
title: A workflow to generate Git patches for auto-fixable issues
published: true
description: My submission to the GitHub Actions x DEV Hackathon 2021!
tags: actionshackathon21, github, opensource
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lpn0gq324yn4p5c3jji5.png 
---

[Instructions]: # (To submit to the GitHub Actions x DEV Hackathon 2021, please fill out all sections.)

Don’t you feel frustrated when you make a trivial change in your codebase, like editing some text using the web editor…:

![](https://static.dt.in.th/uploads/2021/12/06/edit_text.png)

…or bumping some dependencies…:

![](https://static.dt.in.th/uploads/2021/12/06/bump_dep.png)

…only to see your CI build failing because of reasons like these?:

- Prettier doesn’t like it that you don’t wrap lines at 80 characters:

  ![](https://static.dt.in.th/uploads/2021/12/06/prettier_error.png)

- You forgot to update your test snapshots:

  ![](https://static.dt.in.th/uploads/2021/12/06/snapshot_error.png)

- You didn't run `yarn` to update the lockfile:

  ![](https://static.dt.in.th/uploads/2021/12/06/lockfile_error.png)

- Other trivially fixable errors:

  ![](https://static.dt.in.th/uploads/2021/12/06/eslint_fixable.png)

I get very annoyed when issues like this happens. It’s important to put in checks to keep things tidy and ensure coding style is used consistently. But perhaps we can make it a bit less annoying…

I was once on a large codebase where running the linter and the tests takes 5 minutes. When I make simple changes that breaks any formatting or any snapshot, I lose a lot of time: 5 minutes to know that there’s a problem. 5 minutes to run `eslint --fix` or `jest -u` and commit+push the changes. And 5 more minutes to verify the fix on CI.

While it’s important to speed up the CI builds, why not also let the CI generate a patch file that you can instantly apply on your branch?

### My Workflow

**(Before)** Instead of simply running checks and failing the build…:

```yaml
- run: yarn --frozen-lockfile
- run: yarn lint
- run: yarn test
- run: yarn prettier --check .
```

**(After)** …we let GitHub Actions try to fix the auto-fixable problems…:

```yaml
- run: yarn --no-immutable
- run: yarn lint --fix
- run: yarn test --updateSnapshot
- run: yarn prettier --write .
```

…then we stage the changed files and finally use the [Patch Generator](https://github.com/marketplace/actions/patch-generator) action (newly created for this hackathon) to generate a patch command:

```yaml
- run: git add --update
- uses: dtinth/patch-generator-action@v1
```

When this workflow is run and there is any auto-fixable changes, Patch Generator will generate a shell command that you paste into your local machine to instantly apply the required changes. It also works with binary files. And if the changes are too big, you can download the patch file from the build artifacts and apply using the [`git apply`](https://git-scm.com/docs/git-apply) command.

![](https://static.dt.in.th/uploads/2021/12/06/with_this_command_a2.png)

Finally, you can also review the diff from the actions log to see what would happen when you run the above command.

![](https://static.dt.in.th/uploads/2021/12/06/with_this_command_b.png)

### Submission Category:

Maintainer Must-Haves

### Yaml File or Link to Code

- **Example project** ([example PR](https://github.com/dtinth/patch-generator-action-demo/pull/1), [workflow file](https://github.com/dtinth/patch-generator-action-demo/blob/main/.github/workflows/example.yml))

  {% github dtinth/patch-generator-action-demo no-readme %}

- **Patch Generator Action** ([action source](https://github.com/dtinth/patch-generator-action/blob/main/action.yml), [marketplace](https://github.com/marketplace/actions/patch-generator))

  {% github dtinth/patch-generator-action no-readme %}

### Additional Resources / Info

`patch-generator-action` is created as a [composite action](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action). This approach has some benefits over [JavaScript actions](https://docs.github.com/en/actions/creating-actions/creating-a-javascript-action):

- People can fork and modify the action without having to install any build tool or go through any build steps. Development for this action mostly happen in [`github.dev`](https://github.com/github/dev) without any other build tooling.

- Since composite actions uses the same syntax as a workflow, people can also yoink the action code, and put them directly in their workflow files, if they so choose.

I am using the workflow in these open source projects:

- **Bemuse** (Rush + markdown-toc + ESLint + Prettier; [workflow file](https://github.com/bemusic/bemuse/blob/master/.github/workflows/tidy.yml))

  {% github bemusic/bemuse no-readme %}

- **Fresh App Factory** (Yarn + Prettier; [workflow file](https://github.com/fresh-app/factory/blob/main/.github/workflows/tidy.yml))

  {% github fresh-app/factory no-readme %}

- **Patch Generator Action** _(Itself!)_ (Prettier; [workflow file](https://github.com/dtinth/patch-generator-action/blob/main/.github/workflows/tidy.yml))

  {% github dtinth/patch-generator-action no-readme %}

The action is released under the [Unlicense](https://unlicense.org/), i.e., into the public domain.