Skip to content

Commit a0ad4b6

Browse files
Merge pull request #23 from DeDuckProject/claude/faster-glimpse-emoji-W1aEQ
Add emoji reactions to acknowledge and report command status
2 parents fc5c8d0 + 8fa7bfe commit a0ad4b6

5 files changed

Lines changed: 110 additions & 12 deletions

File tree

.github/workflows/demo.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
permissions:
2929
pull-requests: write
3030
contents: write
31+
issues: write
3132

3233
steps:
3334
- uses: actions/checkout@v4
@@ -99,3 +100,24 @@ jobs:
99100
env:
100101
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
101102
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
103+
104+
- name: React with hooray on success
105+
if: >-
106+
github.event_name == 'issue_comment' &&
107+
steps.check.outputs.should-run == 'true' &&
108+
success()
109+
env:
110+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
111+
run: |
112+
gh api repos/$GITHUB_REPOSITORY/issues/comments/${{ github.event.comment.id }}/reactions \
113+
--method POST --field content=hooray || true
114+
115+
- name: React with confused on failure
116+
if: >-
117+
github.event_name == 'issue_comment' &&
118+
failure()
119+
env:
120+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
121+
run: |
122+
gh api repos/$GITHUB_REPOSITORY/issues/comments/${{ github.event.comment.id }}/reactions \
123+
--method POST --field content=confused || true

.github/workflows/glimpse-ack.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# GitGlimpse Acknowledge Workflow
2+
#
3+
# OPTIONAL — this workflow is not required for git-glimpse to work.
4+
# The demo pipeline runs and posts its comment regardless of whether
5+
# this file exists.
6+
#
7+
# What it does: reacts with 👀 on the /glimpse comment as soon as a
8+
# runner is available (~15–30s), giving the commenter immediate visual
9+
# confirmation that their request was received — before the heavy
10+
# pipeline steps begin.
11+
#
12+
# Why it's a separate file: keeping it separate from the main workflow
13+
# means it never shows up as a "skipped" check on pull_request events.
14+
# If it were in the same file as the demo job, GitHub would show an
15+
# "ack (skipped)" entry in the PR checks on every push — noise for
16+
# non-developer reviewers.
17+
#
18+
# ⚠️ Changes only take effect after merging to main (GitHub reads
19+
# issue_comment workflows from the default branch).
20+
name: GitGlimpse Acknowledge
21+
22+
on:
23+
issue_comment:
24+
types: [created]
25+
26+
jobs:
27+
ack:
28+
if: >-
29+
github.event.issue.pull_request != null &&
30+
contains(github.event.comment.body, '/glimpse')
31+
runs-on: ubuntu-latest
32+
permissions:
33+
issues: write
34+
steps:
35+
- name: React with eyes
36+
env:
37+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38+
run: |
39+
gh api repos/$GITHUB_REPOSITORY/issues/comments/${{ github.event.comment.id }}/reactions \
40+
--method POST --field content=eyes || true

CLAUDE.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ pnpm test --watch # watch mode
4949

5050
Integration tests require a running app. See `tests/integration/`.
5151

52+
## External-First Design Principle
53+
54+
git-glimpse is used as a GitHub Action (and in future possibly a GitHub App) by *other* repos —
55+
not just this one. Every change we make must account for the experience of those consumers.
56+
57+
**Rules of thumb:**
58+
- **Seamless by default**: aim for zero-config or minimal-config integration that just works.
59+
- **Control when needed**: if seamless isn't achievable (e.g. workflow-level changes), provide
60+
clear documentation, sample workflow snippets, and ideally a wrapper action.
61+
- **No silent breakage**: changes to action inputs/outputs, config schema, or workflow events must
62+
be backwards-compatible or clearly versioned.
63+
- **Test from the outside**: validate features as if you were a consumer repo, not just via this
64+
repo's internal `demo.yml`.
65+
- **Discuss trade-offs**: if a feature requires consumers to make non-trivial changes (new secrets,
66+
new workflow jobs, new permissions), flag it in the PR for a deliberate decision.
67+
5268
## Branching Convention
5369

5470
- Features: `feat/<name>`

packages/action/src/check.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@ async function check(): Promise<void> {
8989
return;
9090
}
9191

92+
// Acknowledge immediately — this is the earliest action code runs for external users
93+
try {
94+
await octokit.rest.reactions.createForIssueComment({
95+
owner,
96+
repo,
97+
comment_id: context.payload.comment!.id,
98+
content: 'eyes',
99+
});
100+
} catch {
101+
// Non-fatal
102+
}
103+
92104
pullNumber = context.payload.issue!.number;
93105
eventType = 'comment';
94106

packages/action/src/index.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ async function run(): Promise<void> {
7676
let headSha: string;
7777
let eventType: 'push' | 'comment';
7878
let command = null;
79+
let commentId: number | null = null;
80+
81+
const addCommentReaction = async (content: 'eyes' | 'hooray' | 'confused') => {
82+
if (commentId === null) return;
83+
try {
84+
await octokit.rest.reactions.createForIssueComment({
85+
owner,
86+
repo,
87+
comment_id: commentId,
88+
content,
89+
});
90+
} catch {
91+
// Non-fatal
92+
}
93+
};
7994

8095
if (eventName === 'issue_comment') {
8196
// Only handle comments on PRs, not plain issues
@@ -92,20 +107,9 @@ async function run(): Promise<void> {
92107
}
93108

94109
pullNumber = context.payload.issue!.number;
110+
commentId = context.payload.comment!.id;
95111
eventType = 'comment';
96112

97-
// Acknowledge the command with a reaction
98-
try {
99-
await octokit.rest.reactions.createForIssueComment({
100-
owner,
101-
repo,
102-
comment_id: context.payload.comment!.id,
103-
content: 'eyes',
104-
});
105-
} catch {
106-
// Non-fatal: reaction is best-effort
107-
}
108-
109113
// Fetch PR details to get base/head SHAs
110114
const pr = await octokit.rest.pulls.get({ owner, repo, pull_number: pullNumber });
111115
baseSha = pr.data.base.sha;
@@ -212,6 +216,10 @@ async function run(): Promise<void> {
212216
core.info(`Demo comment posted: ${comment.url}`);
213217
core.setOutput('comment-url', comment.url);
214218
core.setOutput('success', String(result.success));
219+
await addCommentReaction('hooray');
220+
} catch (err) {
221+
await addCommentReaction('confused');
222+
throw err;
215223
} finally {
216224
appProcess?.kill();
217225
}

0 commit comments

Comments
 (0)