1
1
name : Format Files
2
2
3
- # cpp
4
- # csharp - https://github.com/dotnet/format ?
5
- # java - prettier-plugin-java
6
- # javascript - prettier
7
- # python - black
8
- # ruby - rufo
9
- # swift - https://github.com/apple/swift-format ?
10
- # typescript - prettier
11
-
12
3
on :
13
4
workflow_dispatch :
14
- pull_request_target :
5
+ pull_request :
15
6
types : [opened, synchronize, reopened]
16
7
8
+ permissions :
9
+ contents : write # write needed only for same-repo pushes; forks get read-only token automatically
10
+
17
11
jobs :
18
- Format :
12
+ format :
19
13
runs-on : ubuntu-latest
20
14
21
- strategy :
22
- matrix :
23
- node-version : [20.x]
24
-
25
15
steps :
26
- - name : Checkout Repository
16
+ - name : Checkout PR HEAD
27
17
uses : actions/checkout@v4
28
18
with :
29
- ref : ${{ github.head_ref }}
30
- fetch-depth : 1
19
+ repository : ${{ github.event.pull_request.head.repo.full_name }}
20
+ ref : ${{ github.event.pull_request.head.sha }}
21
+ fetch-depth : 0
22
+
23
+ - name : Detect fork vs same-repo
24
+ id : ctx
25
+ run : |
26
+ if [ "${{ github.event.pull_request.head.repo.full_name }}" = "${{ github.repository }}" ]; then
27
+ echo "same_repo=true" >> $GITHUB_OUTPUT
28
+ else
29
+ echo "same_repo=false" >> $GITHUB_OUTPUT
30
+ fi
31
31
32
- - name : Use Node.js (dependency)
32
+ - name : Use Node.js
33
33
uses : actions/setup-node@v4
34
34
with :
35
- node-version : ${{ matrix.node-version }}
35
+ node-version : 20
36
36
37
- - name : Install Rufo (dependency)
37
+ - name : Install formatters
38
38
run : |
39
- sudo apt update
39
+ sudo apt-get update
40
40
sudo gem install rufo
41
-
42
- - name : Install Prettier
43
- run : |
44
- npm install -g prettier
45
- npm install -g prettier-plugin-java
46
-
41
+ npm i -g prettier prettier-plugin-java
47
42
- name : Install Black
48
43
uses : BSFishy/pip-action@v1
49
44
with :
50
45
packages : black
51
46
52
- - name : Format
47
+ - name : Run formatters
48
+ run : |
49
+ set -e
50
+ # Use globs; .prettierrc discovered from repo root
51
+ prettier --write "javascript/*.js" || true
52
+ prettier --write "typescript/*.ts" || true
53
+ prettier --write "java/*.java" || true
54
+ rufo ruby || true
55
+ python -m black . || true
56
+
57
+ - name : Check for changes
58
+ id : diff
59
+ run : |
60
+ git status --porcelain
61
+ if [ -n "$(git status --porcelain)" ]; then
62
+ echo "changed=true" >> $GITHUB_OUTPUT
63
+ else
64
+ echo "changed=false" >> $GITHUB_OUTPUT
65
+ fi
66
+
67
+ # Auto-push only for same-repo PRs
68
+ - name : Push formatting changes (same-repo only)
69
+ if : steps.ctx.outputs.same_repo == 'true' && steps.diff.outputs.changed == 'true'
70
+ run : |
71
+ git config user.email "[email protected] "
72
+ git config user.name "Bot-A0"
73
+ git add -A
74
+ git commit -m "🎨 Format files (🛠️ from GitHub Actions)"
75
+ git push "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.event.pull_request.head.repo.full_name }}.git" \
76
+ HEAD:refs/heads/${{ github.event.pull_request.head.ref }}
77
+ env :
78
+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
79
+
80
+ # For forks, upload a patch artifact the author can apply locally: `git apply formatting.patch`
81
+ - name : Create patch (forks only)
82
+ if : steps.ctx.outputs.same_repo == 'false' && steps.diff.outputs.changed == 'true'
53
83
run : |
54
- prettier --config "$GITHUB_WORKSPACE/.prettierrc" --write "$GITHUB_WORKSPACE/javascript/*.js" 2>&1 || true
55
- prettier --config "$GITHUB_WORKSPACE/.prettierrc" --write "$GITHUB_WORKSPACE/typescript/*.ts" 2>&1 || true
56
- prettier --config "$GITHUB_WORKSPACE/.prettierrc" --write "$GITHUB_WORKSPACE/java/*.java" 2>&1 || true
57
- rufo "$GITHUB_WORKSPACE/ruby" 2>&1 || true
58
- python -m black "$GITHUB_WORKSPACE/" 2>&1 || true
84
+ git diff > formatting.patch
85
+ ls -l formatting.patch
86
+
87
+ - name : Upload patch artifact (forks only)
88
+ if : steps.ctx.outputs.same_repo == 'false' && steps.diff.outputs.changed == 'true'
89
+ uses : actions/upload-artifact@v4
90
+ with :
91
+ name : formatting.patch
92
+ path : formatting.patch
93
+ if-no-files-found : error
94
+ retention-days : 7
95
+
96
+ # Leave a comment with instructions on fork PRs
97
+ - name : Comment instructions (forks only)
98
+ if : steps.ctx.outputs.same_repo == 'false' && steps.diff.outputs.changed == 'true'
99
+ uses : actions/github-script@v7
100
+ with :
101
+ script : |
102
+ const body = [
103
+ "I ran the formatters and found changes. Since this is a forked PR, I can't push to your branch.",
104
+ "",
105
+ "**How to apply the patch:**",
106
+ "```bash",
107
+ "curl -L -o formatting.patch \"$ACTIONS_ARTIFACT_URL\" # Download from the job's Artifacts section",
108
+ "git apply formatting.patch",
109
+ "git commit -am \"Apply formatting patch\"",
110
+ "git push",
111
+ "```",
112
+ "",
113
+ "Alternatively, run the same formatters locally: `prettier`, `rufo`, and `black`."
114
+ ].join("\n");
115
+ github.rest.issues.createComment({
116
+ owner: context.repo.owner,
117
+ repo: context.repo.repo,
118
+ issue_number: context.payload.pull_request.number,
119
+ body
120
+ });
59
121
60
- - name : Push
122
+ # Optional: make CI fail if formatting changes were needed (forces author to accept fixes or patch)
123
+ - name : Fail if formatting changes are needed
124
+ if : steps.diff.outputs.changed == 'true' && steps.ctx.outputs.same_repo == 'false'
61
125
run : |
62
- git config --global user.email "[email protected] "
63
- git config --global user.name "Bot-A0"
64
- git add .
65
- git commit -m "🎨 Format files (🛠️ from Github Actions)" || true
66
- git push || true
126
+ echo "Formatting changes required. Patch uploaded as an artifact."
127
+ exit 1
0 commit comments