Skip to content

Commit 76496b3

Browse files
agrawal-ayushclaude
andcommitted
Add SDK regression workflow for GitHub Actions
Adds a workflow_dispatch triggered workflow that runs TestNG sample tests with configurable Maven profile, BrowserStack credentials, and optional pre-built JAR/binary URLs. Outputs build IDs as downloadable artifacts for external assertion runners. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3dd1748 commit 76496b3

1 file changed

Lines changed: 206 additions & 0 deletions

File tree

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
name: SDK Regression Test
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
profile:
7+
description: 'Maven profile to run (e.g. sample-test, sample-local-test)'
8+
required: true
9+
default: 'sample-test'
10+
build_name:
11+
description: 'BrowserStack build name'
12+
required: true
13+
project_name:
14+
description: 'BrowserStack project name'
15+
required: true
16+
bs_username:
17+
description: 'BrowserStack username'
18+
required: true
19+
bs_accesskey:
20+
description: 'BrowserStack access key'
21+
required: true
22+
java_version:
23+
description: 'Java version'
24+
required: false
25+
default: '17'
26+
jar_url:
27+
description: 'Pre-built SDK JAR URL (optional - uses Maven Central LATEST if empty)'
28+
required: false
29+
default: ''
30+
bin_url:
31+
description: 'Pre-built binary URL (optional)'
32+
required: false
33+
default: ''
34+
35+
jobs:
36+
run-test:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@v4
40+
41+
- name: Set up Java
42+
uses: actions/setup-java@v4
43+
with:
44+
distribution: 'temurin'
45+
java-version: ${{ inputs.java_version }}
46+
cache: 'maven'
47+
48+
- name: Download SDK JAR (if jar_url provided)
49+
if: inputs.jar_url != ''
50+
run: |
51+
echo "Downloading SDK JAR from: ${{ inputs.jar_url }}"
52+
JAR_URL="${{ inputs.jar_url }}"
53+
# Add https:// if not present
54+
if [[ ! "$JAR_URL" =~ ^https?:// ]]; then
55+
JAR_URL="https://$JAR_URL"
56+
fi
57+
curl -fSL "$JAR_URL" -o /tmp/browserstack-java-sdk.jar
58+
echo "JAR_PATH=/tmp/browserstack-java-sdk.jar" >> $GITHUB_ENV
59+
60+
- name: Update pom.xml for custom JAR
61+
if: inputs.jar_url != ''
62+
run: |
63+
# Replace the SDK dependency to use system scope with local JAR
64+
python3 - <<'PYEOF'
65+
import xml.etree.ElementTree as ET
66+
67+
ET.register_namespace('', 'http://maven.apache.org/POM/4.0.0')
68+
tree = ET.parse('pom.xml')
69+
root = tree.getroot()
70+
ns = {'m': 'http://maven.apache.org/POM/4.0.0'}
71+
72+
for dep in root.findall('.//m:dependency', ns):
73+
artifact = dep.find('m:artifactId', ns)
74+
if artifact is not None and artifact.text == 'browserstack-java-sdk':
75+
scope = dep.find('m:scope', ns)
76+
if scope is None:
77+
scope = ET.SubElement(dep, 'scope')
78+
scope.text = 'system'
79+
80+
version = dep.find('m:version', ns)
81+
if version is not None:
82+
version.text = '1.0'
83+
84+
sys_path = dep.find('m:systemPath', ns)
85+
if sys_path is None:
86+
sys_path = ET.SubElement(dep, 'systemPath')
87+
sys_path.text = '/tmp/browserstack-java-sdk.jar'
88+
89+
tree.write('pom.xml', xml_declaration=True, encoding='UTF-8')
90+
PYEOF
91+
echo "Updated pom.xml for custom JAR"
92+
cat pom.xml
93+
94+
- name: Download binary (if bin_url provided)
95+
if: inputs.bin_url != ''
96+
run: |
97+
BIN_URL="${{ inputs.bin_url }}"
98+
if [[ ! "$BIN_URL" =~ ^https?:// ]]; then
99+
BIN_URL="https://$BIN_URL"
100+
fi
101+
curl -fSL "$BIN_URL" -o /tmp/binary.zip
102+
cd /tmp && unzip -o binary.zip
103+
BIN_FILE=$(ls /tmp/BrowserStackLocal* 2>/dev/null | head -1)
104+
if [ -n "$BIN_FILE" ]; then
105+
chmod +x "$BIN_FILE"
106+
echo "SDK_CLI_BIN_PATH=$BIN_FILE" >> $GITHUB_ENV
107+
fi
108+
109+
- name: Write browserstack.yml
110+
run: |
111+
cat > browserstack.yml <<'YML'
112+
userName: ${{ inputs.bs_username }}
113+
accessKey: ${{ inputs.bs_accesskey }}
114+
projectName: ${{ inputs.project_name }}
115+
buildName: ${{ inputs.build_name }}
116+
buildIdentifier: '#${BUILD_NUMBER}'
117+
framework: testng
118+
platforms:
119+
- os: Windows
120+
osVersion: 10
121+
browserName: Chrome
122+
browserVersion: latest
123+
parallelsPerPlatform: 1
124+
browserstackLocal: true
125+
debug: true
126+
networkLogs: true
127+
testObservability: true
128+
source: testng:sample-master:v1.1
129+
YML
130+
131+
- name: Run Maven test
132+
id: mvn-test
133+
run: |
134+
export BROWSERSTACK_USERNAME="${{ inputs.bs_username }}"
135+
export BROWSERSTACK_ACCESS_KEY="${{ inputs.bs_accesskey }}"
136+
export BROWSERSTACK_BUILD_NAME="${{ inputs.build_name }}"
137+
export BROWSERSTACK_PROJECT_NAME="${{ inputs.project_name }}"
138+
if [ -n "$SDK_CLI_BIN_PATH" ]; then
139+
export SDK_CLI_BIN_PATH="$SDK_CLI_BIN_PATH"
140+
fi
141+
142+
mvn test -P ${{ inputs.profile }} --batch-mode 2>&1 | tee /tmp/mvn-output.log
143+
MVN_EXIT=${PIPESTATUS[0]}
144+
echo "mvn_exit=$MVN_EXIT" >> $GITHUB_OUTPUT
145+
146+
# Even if mvn returns non-zero (test failures), we still want to extract build IDs
147+
# Only fail if mvn couldn't run at all
148+
if [ $MVN_EXIT -ne 0 ]; then
149+
echo "::warning::Maven exited with code $MVN_EXIT"
150+
fi
151+
152+
- name: Extract build IDs from logs
153+
id: extract
154+
if: always()
155+
run: |
156+
# Extract o11y_build_uuid from javaagent log
157+
O11Y_UUID=""
158+
if [ -f "log/browserstack-javaagent.log" ]; then
159+
O11Y_UUID=$(grep 'automation\.browserstack\.com' log/browserstack-javaagent.log | tail -1 | grep -oP 'builds/\K[a-z0-9]+' || true)
160+
fi
161+
# Fallback: check mvn output
162+
if [ -z "$O11Y_UUID" ]; then
163+
O11Y_UUID=$(grep 'observability.browserstack.com/builds/' /tmp/mvn-output.log | tail -1 | grep -oP 'builds/\K[a-z0-9]+' || true)
164+
fi
165+
echo "o11y_build_uuid=$O11Y_UUID" >> $GITHUB_OUTPUT
166+
echo "Extracted o11y_build_uuid: $O11Y_UUID"
167+
168+
- name: Build results JSON
169+
if: always()
170+
run: |
171+
python3 - <<PYEOF
172+
import json, os
173+
174+
results = {
175+
"build_name": "${{ inputs.build_name }}",
176+
"project_name": "${{ inputs.project_name }}",
177+
"profile": "${{ inputs.profile }}",
178+
"o11y_build_uuid": "${{ steps.extract.outputs.o11y_build_uuid }}",
179+
"mvn_exit_code": int("${{ steps.mvn-test.outputs.mvn_exit || '1' }}"),
180+
"java_version": "${{ inputs.java_version }}",
181+
}
182+
183+
os.makedirs("/tmp/results", exist_ok=True)
184+
with open("/tmp/results/results.json", "w") as f:
185+
json.dump(results, f, indent=2)
186+
187+
print(json.dumps(results, indent=2))
188+
PYEOF
189+
190+
- name: Upload results artifact
191+
if: always()
192+
uses: actions/upload-artifact@v4
193+
with:
194+
name: sdk-regression-results
195+
path: /tmp/results/results.json
196+
retention-days: 7
197+
198+
- name: Upload logs
199+
if: always()
200+
uses: actions/upload-artifact@v4
201+
with:
202+
name: sdk-regression-logs
203+
path: |
204+
log/
205+
/tmp/mvn-output.log
206+
retention-days: 7

0 commit comments

Comments
 (0)