@@ -108,11 +108,79 @@ env:
108108 PYTHON_VERSION : " 3.13.1"
109109
110110jobs :
111+ auto_format_pr :
112+ if : ${{ github.event_name == 'pull_request' }}
113+ runs-on : ubuntu-latest
114+ permissions :
115+ contents : write
116+ pull-requests : write
117+ checks : read
118+ steps :
119+ - name : Checkout PR branch
120+ uses : actions/checkout@v5
121+ with :
122+ ref : ${{ github.event.pull_request.head.ref }}
123+ repository : ${{ github.event.pull_request.head.repo.full_name }}
124+ token : ${{ github.token }}
125+ fetch-depth : 0
126+
127+ - name : Setup Rust
128+ uses : dtolnay/rust-toolchain@stable
129+ with :
130+ components : rustfmt
131+
132+ - name : Run cargo fmt
133+ run : cargo fmt --all
134+
135+ - name : Configure git
136+ run : |
137+ git config user.name "github-actions[bot]"
138+ git config user.email "github-actions[bot]@users.noreply.github.com"
139+
140+ - name : git add
141+ run : git add -u
142+
143+ - name : git commit
144+ id : git-commit
145+ run : git commit -m "run `cargo fmt --all`"
146+ continue-on-error : true # Will fail if nothing to commit
147+
148+ - name : Comment on PR
149+ if : ${{ steps.git_commit.outcome == 'success' }}
150+ uses : marocchino/sticky-pull-request-comment@v2
151+ with :
152+ number : ${{ github.event.pull_request.number }}
153+ message : |
154+ **Code has been automatically formatted**
155+
156+ The code in this PR has been formatted using `cargo fmt --all`.
157+
158+ You may need to pull the latest changes before pushing again:
159+ ```bash
160+ git pull origin ${{ github.event.pull_request.head.ref }}
161+ ```
162+
163+ **Triggered by commit:** `${{ github.event.pull_request.head.sha }}`
164+ **Last formatted:** ${{ github.event.pull_request.updated_at }}
165+ **Run**: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
166+
167+ - name : git push
168+ run : git push origin HEAD:${{ github.event.pull_request.head.ref }}
169+ if : steps.git-commit.outcome == 'success'
170+
171+ # This step is not really needed as the earlier push should cancel this run anyways.
172+ # But we are making sure that we abort if we had badly formatted files.
173+ - name : Exit if changed
174+ run : exit 1
175+ if : ${{ steps.git_commit.outcome == 'success' }}
176+
111177 rust_tests :
112- if : ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
178+ if : ${{ !cancelled() && ! contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
113179 env :
114180 RUST_BACKTRACE : full
115181 name : Run rust tests
182+ needs :
183+ - auto_format_pr
116184 runs-on : ${{ matrix.os }}
117185 timeout-minutes : ${{ contains(matrix.os, 'windows') && 45 || 35 }}
118186 strategy :
@@ -174,8 +242,10 @@ jobs:
174242 if : runner.os == 'macOS'
175243
176244 exotic_targets :
177- if : ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
245+ if : ${{ !cancelled() && ! contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
178246 name : Ensure compilation on various targets
247+ needs :
248+ - auto_format_pr
179249 runs-on : ubuntu-latest
180250 timeout-minutes : 30
181251 steps :
@@ -235,10 +305,12 @@ jobs:
235305 # args: --ignore-rust-version
236306
237307 snippets_cpython :
238- if : ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
308+ if : ${{ !cancelled() && ! contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
239309 env :
240310 RUST_BACKTRACE : full
241311 name : Run snippets and cpython tests
312+ needs :
313+ - auto_format_pr
242314 runs-on : ${{ matrix.os }}
243315 timeout-minutes : ${{ contains(matrix.os, 'windows') && 45 || 35 }}
244316 strategy :
@@ -309,6 +381,8 @@ jobs:
309381
310382 lint :
311383 name : Check Rust code with clippy
384+ needs :
385+ - auto_format_pr
312386 runs-on : ubuntu-latest
313387 steps :
314388 - uses : actions/checkout@v6
@@ -343,8 +417,10 @@ jobs:
343417 incremental_files_only : true
344418
345419 miri :
346- if : ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
420+ if : ${{ !cancelled() && ! contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
347421 name : Run tests under miri
422+ needs :
423+ - auto_format_pr
348424 runs-on : ubuntu-latest
349425 timeout-minutes : 30
350426 env :
@@ -367,8 +443,10 @@ jobs:
367443 MIRIFLAGS : ' -Zmiri-ignore-leaks'
368444
369445 wasm :
370- if : ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
446+ if : ${{ !cancelled() && ! contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
371447 name : Check the WASM package and demo
448+ needs :
449+ - auto_format_pr
372450 runs-on : ubuntu-latest
373451 timeout-minutes : 30
374452 steps :
@@ -430,8 +508,10 @@ jobs:
430508 PUBLISH_BRANCH : master
431509
432510 wasm-wasi :
433- if : ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
511+ if : ${{ !cancelled() && ! contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
434512 name : Run snippets and cpython tests on wasm-wasi
513+ needs :
514+ - auto_format_pr
435515 runs-on : ubuntu-latest
436516 timeout-minutes : 30
437517 steps :
0 commit comments