Skip to content

Commit 16fb10e

Browse files
gusgardclaude
andauthored
Post Detox E2E test failures as PR comments on GitHub (#214)
When Detox tests fail on Bitrise, a script now captures the test output and posts it as a comment on the associated GitHub PR. This lets Claude Code (or any reviewer) consume the failure details directly from GitHub. - Add example/scripts/report-detox-failures.sh that posts formatted failure output to the PR via the GitHub API - Update bitrise.yml Detox Test step to capture output with tee and invoke the reporting script on failure - Requires GITHUB_TOKEN secret to be configured in Bitrise https://claude.ai/code/session_01CfUJmEpVDNXDXfUsih1NMX Co-authored-by: Claude <noreply@anthropic.com>
1 parent 906c9a1 commit 16fb10e

2 files changed

Lines changed: 142 additions & 3 deletions

File tree

bitrise.yml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,22 @@ workflows:
7878
- script@1:
7979
inputs:
8080
- working_dir: example
81-
- content: "#!/usr/bin/env bash\n# fail if any commands fails\nset -e\n# debug
82-
log\nset -x\n \n# we are testing a release device configuration\npnpm
83-
detox test --configuration ios.sim.release --cleanup"
81+
- content: |-
82+
#!/usr/bin/env bash
83+
set -x
84+
85+
# Run detox tests and capture output + exit code
86+
pnpm detox test --configuration ios.sim.release --cleanup 2>&1 | tee /tmp/detox-output.log
87+
DETOX_EXIT_CODE=${PIPESTATUS[0]}
88+
89+
# If tests failed, post a PR comment with the failure details
90+
if [ $DETOX_EXIT_CODE -ne 0 ]; then
91+
echo "Detox tests failed (exit code: $DETOX_EXIT_CODE). Reporting to GitHub PR..."
92+
bash scripts/report-detox-failures.sh /tmp/detox-output.log || echo "Warning: Failed to post PR comment"
93+
fi
94+
95+
# Propagate the original exit code so Bitrise still marks the build as failed
96+
exit $DETOX_EXIT_CODE
8497
title: Detox Test
8598
- save-npm-cache@1: {}
8699
- save-cocoapods-cache@1: {}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Posts Detox E2E test failure output as a GitHub PR comment.
4+
#
5+
# Required environment variables:
6+
# GITHUB_TOKEN - GitHub personal access token with repo/PR comment permissions
7+
# BITRISE_PULL_REQUEST - PR number (set automatically by Bitrise for PR builds)
8+
# GIT_REPOSITORY_URL - Git repo URL (set automatically by Bitrise)
9+
#
10+
# Optional environment variables:
11+
# BITRISE_GIT_COMMIT - Commit SHA (set automatically by Bitrise)
12+
# BITRISE_BUILD_URL - Link to the Bitrise build (set automatically by Bitrise)
13+
#
14+
# Usage:
15+
# pnpm detox test ... 2>&1 | tee /tmp/detox-output.log
16+
# # If tests failed:
17+
# ./scripts/report-detox-failures.sh /tmp/detox-output.log
18+
19+
set -o pipefail
20+
21+
LOG_FILE="${1:?Usage: report-detox-failures.sh <log-file>}"
22+
23+
if [ ! -f "$LOG_FILE" ]; then
24+
echo "Error: Log file not found: $LOG_FILE"
25+
exit 1
26+
fi
27+
28+
# --- Guard: only run for PR builds with a token ---
29+
if [ -z "$BITRISE_PULL_REQUEST" ]; then
30+
echo "Not a PR build (BITRISE_PULL_REQUEST is empty). Skipping PR comment."
31+
exit 0
32+
fi
33+
34+
if [ -z "$GITHUB_TOKEN" ]; then
35+
echo "Warning: GITHUB_TOKEN is not set. Cannot post PR comment."
36+
exit 0
37+
fi
38+
39+
# --- Parse owner/repo from GIT_REPOSITORY_URL ---
40+
# Handles both SSH (git@github.com:owner/repo.git) and HTTPS (https://github.com/owner/repo.git)
41+
REPO_SLUG=""
42+
if [[ "$GIT_REPOSITORY_URL" =~ github\.com[:/]([^/]+/[^/.]+)(\.git)?$ ]]; then
43+
REPO_SLUG="${BASH_REMATCH[1]}"
44+
fi
45+
46+
if [ -z "$REPO_SLUG" ]; then
47+
echo "Error: Could not parse owner/repo from GIT_REPOSITORY_URL: $GIT_REPOSITORY_URL"
48+
exit 1
49+
fi
50+
51+
PR_NUMBER="$BITRISE_PULL_REQUEST"
52+
COMMIT_SHA="${BITRISE_GIT_COMMIT:-unknown}"
53+
BUILD_URL="${BITRISE_BUILD_URL:-}"
54+
55+
# --- Truncate log if too large (GitHub comment limit is 65536 chars) ---
56+
MAX_LOG_CHARS=50000
57+
LOG_CONTENT=$(cat "$LOG_FILE")
58+
if [ ${#LOG_CONTENT} -gt $MAX_LOG_CHARS ]; then
59+
LOG_CONTENT="${LOG_CONTENT:0:$MAX_LOG_CHARS}
60+
61+
... (truncated — full output available in Bitrise build logs)"
62+
fi
63+
64+
# --- Escape for JSON ---
65+
# Use jq to safely encode the log content into a JSON string
66+
LOG_JSON=$(echo "$LOG_CONTENT" | jq -Rs .)
67+
68+
# --- Build comment body ---
69+
BUILD_LINK=""
70+
if [ -n "$BUILD_URL" ]; then
71+
BUILD_LINK="**Build:** $BUILD_URL"
72+
fi
73+
74+
BODY=$(cat <<COMMENT_EOF
75+
## Detox E2E Test Failures
76+
77+
**Configuration:** \`ios.sim.release\`
78+
**Commit:** \`${COMMIT_SHA}\`
79+
${BUILD_LINK}
80+
81+
### Test Output
82+
83+
\`\`\`
84+
${LOG_CONTENT}
85+
\`\`\`
86+
87+
### Relevant Source Files
88+
89+
E2E test files:
90+
- \`example/e2e/firstTest.e2e.test.js\`
91+
- \`example/e2e/renderItems.e2e.test.js\`
92+
93+
Component source files:
94+
- \`src/components/SwiperFlatList/SwiperFlatList.tsx\`
95+
- \`src/components/SwiperFlatList/SwiperFlatListProps.tsx\`
96+
- \`src/components/Pagination/Pagination.tsx\`
97+
98+
Example app source (test IDs and screen setup):
99+
- \`example/src/\`
100+
COMMENT_EOF
101+
)
102+
103+
# Encode the full body as JSON
104+
BODY_JSON=$(echo "$BODY" | jq -Rs .)
105+
106+
# --- Post comment to PR ---
107+
GITHUB_API_URL="https://api.github.com/repos/${REPO_SLUG}/issues/${PR_NUMBER}/comments"
108+
109+
echo "Posting Detox failure report to PR #${PR_NUMBER} on ${REPO_SLUG}..."
110+
111+
HTTP_STATUS=$(curl -s -o /tmp/gh-comment-response.json -w "%{http_code}" \
112+
-X POST \
113+
-H "Authorization: token $GITHUB_TOKEN" \
114+
-H "Accept: application/vnd.github.v3+json" \
115+
-H "Content-Type: application/json" \
116+
-d "{\"body\": ${BODY_JSON}}" \
117+
"$GITHUB_API_URL")
118+
119+
if [ "$HTTP_STATUS" -ge 200 ] && [ "$HTTP_STATUS" -lt 300 ]; then
120+
COMMENT_URL=$(jq -r '.html_url' /tmp/gh-comment-response.json)
121+
echo "Successfully posted PR comment: $COMMENT_URL"
122+
else
123+
echo "Failed to post PR comment. HTTP status: $HTTP_STATUS"
124+
cat /tmp/gh-comment-response.json
125+
exit 1
126+
fi

0 commit comments

Comments
 (0)