spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

Merge pull request #5429 from anthropics/boris/bzxyBrowse files
Add Statsig event logging to GitHub issue workflows
Boris Cherny authored on Aug 9, 2025 · GitHub committed on Aug 9, 2025 parents 2294686 + 5af0b38 · commit ce5b9164fa76
4 changed files+162 -0compared with 2294686
M.github/workflows/auto-close-duplicates.yml
M.github/workflows/claude-dedupe-issues.yml
A.github/workflows/log-issue-events.yml
Mscripts/auto-close-duplicates.ts
@@ -28,3 +28,4 @@
2828 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2929 GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
3030 GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
31+ STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
@@ -29,3 +29,52 @@
2929 anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
3030 claude_env: |
3131 GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
33+ - name: Log duplicate comment event to Statsig
34+ if: always()
35+ env:
36+ STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
37+ run: |
38+ ISSUE_NUMBER=${{ github.event.issue.number || inputs.issue_number }}
39+ REPO=${{ github.repository }}
40+
41+ if [ -z "$STATSIG_API_KEY" ]; then
42+ echo "STATSIG_API_KEY not found, skipping Statsig logging"
43+ exit 0
44+ fi
45+
46+ # Prepare the event payload
47+ EVENT_PAYLOAD=$(jq -n \
48+ --arg issue_number "$ISSUE_NUMBER" \
49+ --arg repo "$REPO" \
50+ --arg triggered_by "${{ github.event_name }}" \
51+ '{
52+ events: [{
53+ eventName: "github_duplicate_comment_added",
54+ value: 1,
55+ metadata: {
56+ repository: $repo,
57+ issue_number: ($issue_number | tonumber),
58+ triggered_by: $triggered_by,
59+ workflow_run_id: "${{ github.run_id }}"
60+ },
61+ time: (now | floor | tostring)
62+ }]
63+ }')
64+
65+ # Send to Statsig API
66+ echo "Logging duplicate comment event to Statsig for issue #${ISSUE_NUMBER}"
67+
68+ RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://events.statsigapi.net/v1/log_event \
69+ -H "Content-Type: application/json" \
70+ -H "STATSIG-API-KEY: ${STATSIG_API_KEY}" \
71+ -d "$EVENT_PAYLOAD")
72+
73+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
74+ BODY=$(echo "$RESPONSE" | head -n-1)
75+
76+ if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 202 ]; then
77+ echo "Successfully logged duplicate comment event for issue #${ISSUE_NUMBER}"
78+ else
79+ echo "Failed to log duplicate comment event for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
80+ fi
@@ -1,0 +1,68 @@
1+name: Log GitHub Issue Events
2+
3+on:
4+ issues:
5+ types: [opened]
6+
7+jobs:
8+ log-issue-created:
9+ runs-on: ubuntu-latest
10+ timeout-minutes: 5
11+ permissions:
12+ contents: read
13+ issues: read
14+
15+ steps:
16+ - name: Log issue creation to Statsig
17+ env:
18+ STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
19+ run: |
20+ ISSUE_NUMBER=${{ github.event.issue.number }}
21+ REPO=${{ github.repository }}
22+ ISSUE_TITLE="${{ github.event.issue.title }}"
23+ AUTHOR="${{ github.event.issue.user.login }}"
24+ CREATED_AT="${{ github.event.issue.created_at }}"
25+
26+ if [ -z "$STATSIG_API_KEY" ]; then
27+ echo "STATSIG_API_KEY not found, skipping Statsig logging"
28+ exit 0
29+ fi
30+
31+ # Prepare the event payload
32+ EVENT_PAYLOAD=$(jq -n \
33+ --arg issue_number "$ISSUE_NUMBER" \
34+ --arg repo "$REPO" \
35+ --arg title "$ISSUE_TITLE" \
36+ --arg author "$AUTHOR" \
37+ --arg created_at "$CREATED_AT" \
38+ '{
39+ events: [{
40+ eventName: "github_issue_created",
41+ value: 1,
42+ metadata: {
43+ repository: $repo,
44+ issue_number: ($issue_number | tonumber),
45+ issue_title: $title,
46+ issue_author: $author,
47+ created_at: $created_at
48+ },
49+ time: (now | floor | tostring)
50+ }]
51+ }')
52+
53+ # Send to Statsig API
54+ echo "Logging issue creation to Statsig for issue #${ISSUE_NUMBER}"
55+
56+ RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://events.statsigapi.net/v1/log_event \
57+ -H "Content-Type: application/json" \
58+ -H "STATSIG-API-KEY: ${STATSIG_API_KEY}" \
59+ -d "$EVENT_PAYLOAD")
60+
61+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
62+ BODY=$(echo "$RESPONSE" | head -n-1)
63+
64+ if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 202 ]; then
65+ echo "Successfully logged issue creation for issue #${ISSUE_NUMBER}"
66+ else
67+ echo "Failed to log issue creation for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
68+ fi
@@ -51,6 +51,42 @@
5151 return match ? parseInt(match[1], 10) : null;
5252 }
5353
54+async function logStatsigEvent(eventName: string, value: number, metadata: Record<string, any>): Promise<void> {
55+ const statsigApiKey = process.env.STATSIG_API_KEY;
56+ if (!statsigApiKey) {
57+ console.log("[DEBUG] STATSIG_API_KEY not found, skipping Statsig logging");
58+ return;
59+ }
60+
61+ const eventPayload = {
62+ events: [{
63+ eventName,
64+ value,
65+ metadata,
66+ time: Math.floor(Date.now()).toString()
67+ }]
68+ };
69+
70+ try {
71+ const response = await fetch('https://events.statsigapi.net/v1/log_event', {
72+ method: 'POST',
73+ headers: {
74+ 'Content-Type': 'application/json',
75+ 'STATSIG-API-KEY': statsigApiKey
76+ },
77+ body: JSON.stringify(eventPayload)
78+ });
79+
80+ if (response.ok) {
81+ console.log(`[DEBUG] Successfully logged Statsig event: ${eventName}`);
82+ } else {
83+ console.log(`[DEBUG] Failed to log Statsig event: ${response.status} ${response.statusText}`);
84+ }
85+ } catch (error) {
86+ console.log(`[DEBUG] Error logging to Statsig: ${error}`);
87+ }
88+}
89+
5490 async function closeIssueAsDuplicate(
5591 owner: string,
5692 repo: string,
@@ -80,6 +116,14 @@
80116 🤖 Generated with [Claude Code](https://claude.ai/code)`
81117 }
82118 );
119+
120+ // Log to Statsig
121+ await logStatsigEvent('github_issue_closed_as_duplicate', 1, {
122+ repository: `${owner}/${repo}`,
123+ issue_number: issueNumber,
124+ duplicate_of_issue: duplicateOfNumber,
125+ closed_by: 'auto-close-script'
126+ });
83127 }
84128
85129 async function autoCloseDuplicates(): Promise<void> {