autofix.ci logo

Getting Started

To setup autofix.ci, do the following:

  1. Install our GitHub App.

    This provides autofix.ci with the necessary permissions to update pull requests.

  2. Create .github/workflows/autofix.yml with the following content:

    name: autofix.ci  # needed to securely identify the workflow
    
    on:
      pull_request:
      push:
        branches: [ "main" ]
    permissions:
      contents: read
    
    jobs:
      autofix:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
    
          # TODO: add all code-fixing here.
    
          - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
    

    Limiting the runner's permissions and pinning the autofix action to a specific commit hash instead of a tag is not required, but makes our workflow more resilient against supply chain attacks.[1]

  3. Add a job that auto-fixes your codebase.

    Replace the comment in the file above with the code-fixing tools of your choice.
    Take a look at the examples below!

Examples

You can combine all the example steps below, but keep them in a single job with only one call to the autofix action! :)

Python

This example demonstrates the use of ruff with autofix.ci. We use uv to install deterministic versions of all tools, but you can also pip install or use an existing requirements.txt file.

ruff
name: autofix.ci
on:
  workflow_call:
  pull_request:
  push:
    branches: [ "main" ]
permissions:
  contents: read

jobs:
  autofix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Use uv to ensure we have the same ruff version in CI and locally.
      - uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a
        with:
          version: "0.4.20"
      # Fix lint errors
      - run: uv run ruff check --fix-only .
      # Format code
      - run: uv run ruff format .

      - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c

Of course, there are more autofixers than just ruff! You may also want to check out black, pyupgrade, reorder_python_imports, autoflake, yesqa, isort, blacken-docs, yapf, autopep8, docformatter, or μsort.

TypeScript / JavaScript / HTML / CSS

Here's a simple workflow that formats your TypeScript or JavaScript code using Prettier:

name: autofix.ci
on:
  pull_request:
  push:
    branches: [ "main" ]
permissions:
  contents: read

jobs:
  autofix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 16

      - run: npm ci
      - run: npx prettier --write .

      - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c

Alternatively, you may want to check out standardjs!

Rust

Here's a simple workflow that rustfmts your repo and applies clippy's suggestions:

name: autofix.ci
on:
  workflow_call:
  pull_request:
  push:
    branches: [ "main" ]
permissions:
  contents: read

env:
  rust_clippy: 1.65  # MSRV

jobs:
  autofix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: autofix-${{ hashFiles('**/Cargo.lock') }}
          
      - run: rustup toolchain install ${{ env.rust_clippy }} --profile minimal --component rustfmt --component clippy
      - run: rustup default ${{ env.rust_clippy }}

      - run: cargo clippy --fix --workspace
      - run: cargo fmt --all

      - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c

You can of course switch to a different Rust toolchain first, for example if you are using nightly rustfmt.

Crab fact: autofix.ci's backend is written in Rust. 🦀

Go

Here's a simple workflow that gofmts your repo:

name: autofix.ci
on:
  pull_request:
  push:
    branches: [ "main" ]
permissions:
  contents: read

jobs:
  autofix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.17'

      # goimports works like gofmt, but also fixes imports.
      # see https://pkg.go.dev/golang.org/x/tools/cmd/goimports
      - run: go install golang.org/x/tools/cmd/goimports@latest
      - run: goimports -w .
      # of course we can also do just this instead:
      # - run: gofmt -w .

      - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c

Images

With a bit of creativity, autofix.ci is not limited to code formatting. For example, the following workflow shrinks all PNG files:

name: autofix.ci
on:
  pull_request:
  push:
    branches: [ "main" ]
permissions:
  contents: read

jobs:
  autofix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Optimize all PNGs with https://pngquant.org/
      - run: sudo apt-get update && sudo apt-get install -y pngquant
      - name: Run pngquant
        run: |
          shopt -s globstar
          pngquant -f --ext .png --skip-if-larger -- **/*.png

      - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c

pre-commit hooks

If your existing workflow is based on pre-commit.com hooks, you should use pre-commit.ci instead of autofix.ci. Of course, you can also integrate pre-commit hooks in your autofix.ci workflow:

name: autofix.ci
on:
  pull_request:
  push:
    branches: [ "main" ]
permissions:
  contents: read

jobs:
  autofix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - run: pip install pre-commit
      - run: pre-commit run --all-files

      - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c