# diff-shades workflow (psf/black)

> The diff-shades workflow from psf/black, explained and optimized by Latchkey.

Source: https://latchkey.dev/workflows/psf-black-diff-shades  
Upstream: [psf/black](https://github.com/psf/black/blob/main/.github/workflows/diff_shades.yml) (.github/workflows/diff_shades.yml), licence MIT

## What it does

This is the diff-shades workflow from the psf/black repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

## The workflow

```yaml
name: diff-shades

on:
  push:
    branches: [main]
    paths:
      - src/**
      - pyproject.toml
      - scripts/diff_shades_gha_helper.py
      - .github/workflows/diff_shades.yml
      - .github/workflows/diff_shades_comment.yml

  pull_request:
    paths:
      - src/**
      - pyproject.toml
      - scripts/diff_shades_gha_helper.py
      - .github/workflows/diff_shades.yml
      - .github/workflows/diff_shades_comment.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
  cancel-in-progress: true

env:
  HATCH_BUILD_HOOKS_ENABLE: "1"
  # Clang is less picky with the C code it's given than gcc (and may generate faster
  # binaries too).
  CC: clang-18

permissions: {}

jobs:
  configure:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-config.outputs.matrix }}

    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
        with:
          persist-credentials: false

      - name: Set up Python
        uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
        with:
          python-version: "3.14"
          pip-version: "25.3"
          pip-install: --group diff-shades --group diff-shades-comment

      - name: Calculate run configuration & metadata
        id: set-config
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: python scripts/diff_shades_gha_helper.py config

  analysis-base:
    name: analysis / base / ${{ matrix.mode }}
    needs: configure
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include: ${{ fromJson(needs.configure.outputs.matrix) }}

    steps:
      - name: Checkout this repository (full clone)
        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
        with:
          # The baseline revision could be rather old so a full clone is ideal.
          fetch-depth: 0
          persist-credentials: false

      - name: Set up Python
        uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
        with:
          python-version: "3.14"
          pip-version: "25.3"
          pip-install: --group diff-shades

      - name: Configure git
        run: |
          git config user.name "diff-shades-gha"
          git config user.email "diff-shades-gha@example.com"

      - name: Attempt to use cached baseline analysis
        id: baseline-cache
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: ${{ matrix.baseline-analysis }}
          key: ${{ matrix.baseline-cache-key }}

      - name: Build and install baseline revision
        if: steps.baseline-cache.outputs.cache-hit != 'true'
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: |
          ${{ matrix.baseline-setup-cmd }}
          python -m pip install .

      - name: Analyze baseline revision
        if: steps.baseline-cache.outputs.cache-hit != 'true'
        run:
          diff-shades analyze ${{ matrix.baseline-analysis }} --work-dir projects-cache/
          --force-${{ matrix.style }}-style -v

      - name: Upload baseline analysis
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: ${{ matrix.baseline-analysis }}
          path: ${{ matrix.baseline-analysis }}

  analysis-target:
    name: analysis / target / ${{ matrix.mode }}
    needs: configure
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include: ${{ fromJson(needs.configure.outputs.matrix) }}

    steps:
      - name: Checkout this repository (full clone)
        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
        with:
          # The baseline revision could be rather old so a full clone is ideal.
          fetch-depth: 0
          persist-credentials: false

      - name: Set up Python
        uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
        with:
          python-version: "3.14"
          pip-version: "25.3"
          pip-install: --group diff-shades

      - name: Configure git
        run: |
          git config user.name "diff-shades-gha"
          git config user.email "diff-shades-gha@example.com"

      - name: Build and install target revision
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: |
          ${{ matrix.target-setup-cmd }}
          python -m pip install .

      # Pull it from previous runs - we're NOT trying to get it from this run
      # (but it wouldn't cause problems if we theoretically did)
      - name: Attempt to find baseline analysis
        id: baseline-cache
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: ${{ matrix.baseline-analysis }}
          key: ${{ matrix.baseline-cache-key }}

      - name: Analyze target revision (with repeated projects)
        if: steps.baseline-cache.outputs.cache-hit == 'true'
        run: |
          diff-shades analyze ${{ matrix.target-analysis }} --work-dir projects-cache/ \
          --force-${{ matrix.style }}-style -v \
          --repeat-projects-from ${{ matrix.baseline-analysis }}

      - name: Analyze target revision (without repeated projects)
        if: steps.baseline-cache.outputs.cache-hit != 'true'
        run:
          diff-shades analyze ${{ matrix.target-analysis }} --work-dir projects-cache/
          --force-${{ matrix.style }}-style -v

      - name: Upload target analysis
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: ${{ matrix.target-analysis }}
          path: ${{ matrix.target-analysis }}

      - name: Check for failed files for target revision
        run: diff-shades show-failed --check --show-log ${{ matrix.target-analysis }}

  compare:
    name: compare / ${{ matrix.mode }}
    needs: ["configure", "analysis-base", "analysis-target"]
    if: ${{ !cancelled() }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include: ${{ fromJson(needs.configure.outputs.matrix) }}

    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
        with:
          persist-credentials: false

      - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          merge-multiple: true

      - name: Set up Python
        uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
        with:
          python-version: "3.14"
          pip-version: "25.3"
          pip-install: --group diff-shades --group diff-shades-comment

      - name: Generate HTML diff report
        run: |
          diff-shades --dump-html diff.html \
          compare --diff ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}

      - name: Upload diff report
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: ${{ matrix.style }}-diff.html
          path: diff.html

      - name: Generate summary file (PR only)
        if: github.event_name == 'pull_request'
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: |
          python scripts/diff_shades_gha_helper.py comment-body \
          ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }} \
          ${{ matrix.style }} ${{ matrix.mode }}

      - name: Upload summary file (PR only)
        if: github.event_name == 'pull_request'
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: .${{ matrix.style }}.pr-comment.md
          path: .${{ matrix.style }}.pr-comment.md
          include-hidden-files: true

      - name: Verify zero changes (PR only)
        if: matrix.mode == 'assert-no-changes'
        run: |
          diff-shades compare --check \
          ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }} || \
          (echo "Please verify you didn't change the stable code style unintentionally!" \
          && exit 1)
```

## FAQ

### What does the diff-shades workflow (psf/black) workflow do?

This is the diff-shades workflow from the psf/black repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

### What CI health grade does this workflow get?

This Python workflow grades C. Paste your own workflow into the Latchkey grader to see its grade and the exact fixes.

### How can I improve this Python workflow?

Add caching and job timeouts. Latchkey applies these automatically on managed runners when you point runs-on at Latchkey.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
