@@ -3,6 +3,8 @@ name: D2 Gen
3
3
on :
4
4
pull_request :
5
5
branches : [ main ]
6
+ issue_comment :
7
+ types : [created]
6
8
7
9
concurrency :
8
10
group : d2gen-${{ github.ref }}-${{ github.event_name }}
@@ -15,26 +17,76 @@ permissions:
15
17
jobs :
16
18
d2gen :
17
19
runs-on : ubuntu-latest
20
+ # Skip workflow if triggered by comment reaction but not on a PR
21
+ if : github.event_name == 'pull_request' || (github.event_name == 'issue_comment' && github.event.issue.pull_request)
18
22
# container: terrastruct/d2:latest
19
23
steps :
20
24
- name : Checkout code
21
25
uses : actions/checkout@v4
22
26
with :
23
27
token : ${{ secrets.GITHUB_TOKEN }}
24
28
fetch-depth : 0
25
- ref : ${{ github.head_ref }}
29
+ ref : ${{ github.event_name == 'pull_request' && github.head_ref || github.event.issue.pull_request.head.ref }}
30
+
31
+ - name : Handle comment reaction
32
+ if : github.event_name == 'issue_comment'
33
+ id : handle_reaction
34
+ uses : actions/github-script@v7
35
+ with :
36
+ script : |
37
+ const comment = context.payload.comment;
38
+ const issue = context.payload.issue;
39
+
40
+ // Check if this comment is about SVG files
41
+ if (!comment.body.includes('SVG Files Updated')) {
42
+ console.log('Comment is not about SVG files, skipping workflow');
43
+ core.setOutput('skip_workflow', 'true');
44
+ return;
45
+ }
46
+
47
+ // Get reactions for this comment
48
+ const { data: reactions } = await github.rest.reactions.listForIssueComment({
49
+ owner: context.repo.owner,
50
+ repo: context.repo.repo,
51
+ comment_id: comment.id
52
+ });
53
+
54
+ const thumbsUp = reactions.find(r => r.content === '+1');
55
+ const thumbsDown = reactions.find(r => r.content === '-1');
56
+
57
+ if (thumbsUp) {
58
+ console.log('👍 reaction detected - will commit changes');
59
+ core.setOutput('user_approved', 'true');
60
+ } else if (thumbsDown) {
61
+ console.log('👎 reaction detected - will skip changes');
62
+ core.setOutput('user_approved', 'false');
63
+ } else {
64
+ console.log('No relevant reaction found');
65
+ core.setOutput('user_approved', 'false');
66
+ }
67
+
68
+ core.setOutput('skip_workflow', 'false');
69
+
70
+ - name : Exit early if workflow should be skipped
71
+ if : github.event_name == 'issue_comment' && steps.handle_reaction.outputs.skip_workflow == 'true'
72
+ run : |
73
+ echo "Skipping workflow - comment not related to SVG generation"
74
+ exit 0
26
75
27
76
- name : Install D2
77
+ if : github.event_name == 'pull_request'
28
78
run : |
29
79
curl -fsSL https://d2lang.com/install.sh | sh -s -- --tala
30
80
echo "$HOME/.local/bin" >> $GITHUB_PATH
31
81
32
82
- name : Generate SVG images from D2
83
+ if : github.event_name == 'pull_request'
33
84
env :
34
85
TSTRUCT_TOKEN : ${{ secrets.TSTRUCT_TOKEN }}
35
86
run : make d2gen-all
36
87
37
88
- name : Check for changes in SVG files
89
+ if : github.event_name == 'pull_request'
38
90
id : check_changes
39
91
run : |
40
92
if git diff --quiet '*.svg'; then
@@ -46,15 +98,15 @@ jobs:
46
98
fi
47
99
48
100
- name : Get changed SVG files
49
- if : steps.check_changes.outputs.changed == 'true'
101
+ if : github.event_name == 'pull_request' && steps.check_changes.outputs.changed == 'true'
50
102
id : get_changed_files
51
103
run : |
52
104
echo "files<<EOF" >> $GITHUB_OUTPUT
53
105
git diff --name-only '*.svg'
54
106
echo "EOF" >> $GITHUB_OUTPUT
55
107
56
108
- name : Create PR comment for approval
57
- if : steps.check_changes.outputs.changed == 'true'
109
+ if : github.event_name == 'pull_request' && steps.check_changes.outputs.changed == 'true'
58
110
id : pr_comment
59
111
uses : actions/github-script@v7
60
112
with :
@@ -71,12 +123,12 @@ jobs:
71
123
changedFiles,
72
124
"```",
73
125
"",
74
- "Would you like me to commit these changes to this PR? ",
126
+ "**This CI run will fail** until you make a choice. React to this comment: ",
75
127
"",
76
- "- 👍 **Yes** - Automatically commit the updated SVG files",
77
- "- 👎 **No** - Skip committing, CI will pass without the changes ",
128
+ "- 👍 **Yes** - React to automatically commit the updated SVG files and re-run CI ",
129
+ "- 👎 **No** - React to skip committing and re-run CI (it will pass) ",
78
130
"",
79
- "Please react to this comment with your choice."
131
+ "After you react, the CI will automatically run again with your choice."
80
132
].join("\\n");
81
133
82
134
const { data: comment } = await github.rest.issues.createComment({
@@ -88,75 +140,9 @@ jobs:
88
140
89
141
return comment.id;
90
142
91
- - name : Wait for user reaction
92
- if : steps.check_changes.outputs.changed == 'true'
93
- id : wait_reaction
94
- uses : actions/github-script@v7
95
- with :
96
- script : |
97
- const commentId = parseInt('${{ steps.pr_comment.outputs.result }}');
98
- console.log('Starting wait for user reaction, commentId:', commentId);
99
- const maxWaitTime = 60000; // 1 minute for testing
100
- const pollInterval = 5000; // 5 seconds
101
- let elapsedTime = 0;
102
-
103
- while (elapsedTime < maxWaitTime) {
104
- console.log(`Polling for reactions (${elapsedTime/1000}s elapsed)...`);
105
- const { data: reactions } = await github.rest.reactions.listForIssueComment({
106
- owner: context.repo.owner,
107
- repo: context.repo.repo,
108
- comment_id: commentId
109
- });
110
-
111
- const thumbsUp = reactions.find(r => r.content === '+1');
112
- const thumbsDown = reactions.find(r => r.content === '-1');
113
-
114
- if (thumbsUp) {
115
- console.log('User approved changes with 👍');
116
- require('fs').appendFileSync(process.env.GITHUB_OUTPUT, 'result=approve\n');
117
- return 'approve';
118
- } else if (thumbsDown) {
119
- console.log('User declined changes with 👎');
120
- require('fs').appendFileSync(process.env.GITHUB_OUTPUT, 'result=decline\n');
121
- return 'decline';
122
- }
123
-
124
- await new Promise(resolve => setTimeout(resolve, pollInterval));
125
- elapsedTime += pollInterval;
126
- }
127
-
128
- console.log('Timeout reached, defaulting to decline');
129
- require('fs').appendFileSync(process.env.GITHUB_OUTPUT, 'result=decline\n');
130
- return 'decline';
131
-
132
- - name : Debug wait reaction step
133
- if : always()
134
- run : |
135
- echo "🔍 Checking if wait_reaction step ran..."
136
- echo "Wait reaction step conclusion: ${{ steps.wait_reaction.conclusion }}"
137
- echo "Wait reaction step outcome: ${{ steps.wait_reaction.outcome }}"
138
- echo "Wait reaction step outputs.result: '${{ steps.wait_reaction.outputs.result }}'"
139
-
140
- - name : Always debug outputs
141
- run : |
142
- echo "🐛 Always running debug - checking all outputs..."
143
- echo "Changed files detected: '${{ steps.check_changes.outputs.changed }}'"
144
- echo "User reaction result: '${{ steps.wait_reaction.outputs.result }}'"
145
- echo "PR comment ID: '${{ steps.pr_comment.outputs.result }}'"
146
- echo "Condition 1 (changes): ${{ steps.check_changes.outputs.changed == 'true' }}"
147
- echo "Condition 2 (approve): ${{ steps.wait_reaction.outputs.result == 'approve' }}"
148
- echo "Combined condition: ${{ steps.check_changes.outputs.changed == 'true' && steps.wait_reaction.outputs.result == 'approve' }}"
149
-
150
- - name : Debug step conditions
151
- if : steps.check_changes.outputs.changed == 'true'
152
- run : |
153
- echo "🐛 Conditional debug (changes detected)..."
154
- echo "Changed files detected: ${{ steps.check_changes.outputs.changed }}"
155
- echo "User reaction result: ${{ steps.wait_reaction.outputs.result }}"
156
- echo "Will commit changes: ${{ steps.check_changes.outputs.changed == 'true' && steps.wait_reaction.outputs.result == 'approve' }}"
157
143
158
144
- name : Commit and push changes
159
- if : steps.check_changes.outputs.changed == 'true' # && steps.wait_reaction .outputs.result == 'approve '
145
+ if : github.event_name == 'issue_comment' && steps.handle_reaction .outputs.user_approved == 'true '
160
146
run : |
161
147
echo "🔧 Setting up git configuration..."
162
148
git config --local user.email "[email protected] "
@@ -184,40 +170,52 @@ jobs:
184
170
git push
185
171
186
172
- name : Update PR comment with result
187
- if : steps.check_changes.outputs.changed == 'true '
173
+ if : github.event_name == 'issue_comment '
188
174
uses : actions/github-script@v7
189
175
with :
190
176
script : |
191
- const commentId = parseInt('${{ steps.pr_comment.outputs.result }}') ;
192
- const action = '${{ steps.wait_reaction .outputs.result }}';
177
+ const comment = context.payload.comment ;
178
+ const userApproved = '${{ steps.handle_reaction .outputs.user_approved }}';
193
179
194
180
let updateBody;
195
- if (action === 'approve ') {
181
+ if (userApproved === 'true ') {
196
182
updateBody = [
197
183
"## SVG Files Updated ✅",
198
184
"",
199
185
"The updated SVG files have been successfully committed to this PR.",
200
186
"",
201
- "**Status:** Changes committed automatically based on user approval."
187
+ "**Status:** Changes committed automatically based on user approval (👍 reaction) ."
202
188
].join("\\n");
203
189
} else {
204
190
updateBody = [
205
191
"## SVG Files Updated ⏭️",
206
192
"",
207
- "The SVG files have changes but were not committed based on user choice or timeout .",
193
+ "The SVG files had changes but were not committed based on user choice.",
208
194
"",
209
- "**Status:** CI will pass without committing the changes."
195
+ "**Status:** CI passed without committing the changes (👎 reaction or no approval) ."
210
196
].join("\\n");
211
197
}
212
198
213
199
await github.rest.issues.updateComment({
214
200
owner: context.repo.owner,
215
201
repo: context.repo.repo,
216
- comment_id: commentId ,
202
+ comment_id: comment.id ,
217
203
body: updateBody
218
204
});
219
205
220
- - name : Always pass CI
206
+ - name : Fail CI if changes detected and no user approval
207
+ if : github.event_name == 'pull_request' && steps.check_changes.outputs.changed == 'true'
208
+ run : |
209
+ echo "❌ SVG files need to be updated but no user approval received"
210
+ echo "Please react to the comment above to approve or decline the changes"
211
+ exit 1
212
+
213
+ - name : Pass CI - no changes or user handled reaction
221
214
run : |
222
- echo "SVG generation workflow completed successfully"
215
+ echo "✅ SVG generation workflow completed successfully"
216
+ if [[ "${{ github.event_name }}" == "pull_request" ]]; then
217
+ echo "No SVG changes detected"
218
+ else
219
+ echo "User reaction processed"
220
+ fi
223
221
exit 0
0 commit comments