44 push :
55 branches :
66 - " **"
7- pull_request : {}
7+ paths-ignore :
8+ - " **/*.md"
9+ - " docs/**"
10+ pull_request :
11+ paths-ignore :
12+ - " **/*.md"
13+ - " docs/**"
814 workflow_dispatch : {}
915
1016permissions :
1117 contents : read
1218 actions : write
1319
1420jobs :
15- build-and-test :
21+ integration-tests :
22+ name : Integration Tests (Python 3.12 + Hiero Solo, shard ${{ matrix.shard_label }})
1623 runs-on : ubuntu-latest
17-
1824 strategy :
1925 fail-fast : false
2026 matrix :
21- python-version : ["3.10", "3.11", "3.12", "3.13", "3.14"]
27+ include :
28+ - shard_index : 0
29+ shard_label : " 1/2"
30+ - shard_index : 1
31+ shard_label : " 2/2"
2232
2333 steps :
2434 - name : Harden the runner (Audit all outbound calls)
@@ -29,10 +39,10 @@ jobs:
2939 - name : Checkout repository
3040 uses : actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
3141
32- - name : Set up Python ${{ matrix.python-version }}
42+ - name : Set up Python 3.12
3343 uses : actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
3444 with :
35- python-version : ${{ matrix.python-version }}
45+ python-version : " 3.12 "
3646 cache : " pip"
3747
3848 - name : Install uv
@@ -53,50 +63,89 @@ jobs:
5363 with :
5464 installMirrorNode : true
5565
56- - name : Set environment variables
57- run : |
58- echo "OPERATOR_ID=${{ steps.solo.outputs.accountId }}"
59- echo "OPERATOR_KEY=${{ steps.solo.outputs.privateKey }}"
60- echo "ADMIN_KEY=${{ steps.solo.outputs.privateKey }}"
61- echo "PUBLIC_KEY=${{ steps.solo.outputs.publicKey }}"
62-
63- - name : Install your package
64- run : pip install -e .
65-
66- # #############################################
67- # INTEGRATION TESTS
68- # #############################################
69-
70- - name : Run all integration tests
66+ - name : Run integration tests
7167 id : integration
7268 continue-on-error : true
7369 shell : bash
7470 env :
71+ SHARD_INDEX : ${{ matrix.shard_index }}
72+ SHARD_TOTAL : " 2"
7573 OPERATOR_ID : ${{ steps.solo.outputs.accountId }}
7674 OPERATOR_KEY : ${{ steps.solo.outputs.privateKey }}
7775 ADMIN_KEY : ${{ steps.solo.outputs.privateKey }}
7876 PUBLIC_KEY : ${{ steps.solo.outputs.publicKey }}
7977 NETWORK : solo
8078 run : |
8179 set -o pipefail
82- echo "🚀 Running integration tests..."
83- uv run pytest tests/integration -v --disable-warnings --continue-on-collection-errors 2>&1 | tee result_integration.log
80+ echo "🚀 Running integration tests for shard ${SHARD_INDEX}/${SHARD_TOTAL}..."
81+ mapfile -t integration_tests < <(find tests/integration -maxdepth 1 -type f -name "*_test.py" | sort)
82+ shard_tests=()
83+ for i in "${!integration_tests[@]}"; do
84+ if (( i % SHARD_TOTAL == SHARD_INDEX )); then
85+ shard_tests+=("${integration_tests[$i]}")
86+ fi
87+ done
88+
89+ if [ ${#shard_tests[@]} -eq 0 ]; then
90+ echo "❌ No integration tests selected for shard ${SHARD_INDEX}/${SHARD_TOTAL}"
91+ echo "exit_code=1" >> $GITHUB_OUTPUT
92+ exit 0
93+ fi
94+
95+ echo "Selected ${#shard_tests[@]} integration test files:"
96+ printf ' - %s\n' "${shard_tests[@]}"
97+ uv run pytest "${shard_tests[@]}" -v --disable-warnings --continue-on-collection-errors 2>&1 | tee result_integration.log
8498 pytest_exit=${PIPESTATUS[0]}
85- echo "integration_failed=$pytest_exit" >> $GITHUB_OUTPUT
86- cat result_integration.log
99+ echo "exit_code=$pytest_exit" >> $GITHUB_OUTPUT
87100 if [ $pytest_exit -ne 0 ]; then
88101 echo "❌ Some integration tests failed"
89102 echo "Failed tests:"
90- grep -E 'FAILED ' result_integration.log || true
103+ grep -E 'FAILED |ERROR ' result_integration.log || true
91104 else
92105 echo "✅ All integration tests passed"
93106 fi
94107
95- # #############################################
96- # UNIT TESTS
97- # #############################################
108+ - name : Fail job if integration tests failed
109+ if : steps.integration.outputs.exit_code != '0'
110+ shell : bash
111+ run : |
112+ echo "❌ Integration tests failed. See logs above."
113+ exit 1
114+
115+ unit-tests :
116+ name : Unit Tests (Python ${{ matrix.python-version }})
117+ runs-on : ubuntu-latest
118+
119+ strategy :
120+ fail-fast : false
121+ matrix :
122+ python-version : ["3.10", "3.11", "3.12", "3.13", "3.14"]
123+
124+ steps :
125+ - name : Harden the runner (Audit all outbound calls)
126+ uses : step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0
127+ with :
128+ egress-policy : audit
129+
130+ - name : Checkout repository
131+ uses : actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
132+
133+ - name : Set up Python ${{ matrix.python-version }}
134+ uses : actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
135+ with :
136+ python-version : ${{ matrix.python-version }}
137+ cache : " pip"
138+
139+ - name : Install uv
140+ uses : astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
141+
142+ - name : Install setuptools wheel
143+ run : pip install --upgrade pip setuptools wheel
144+
145+ - name : Install dependencies
146+ run : uv sync --all-extras --dev
98147
99- - name : Run all unit tests
148+ - name : Run unit tests
100149 id : unit
101150 continue-on-error : true
102151 shell : bash
@@ -105,55 +154,54 @@ jobs:
105154 echo "🚀 Running unit tests..."
106155 uv run pytest tests/unit -v --disable-warnings --continue-on-collection-errors 2>&1 | tee result_unit.log
107156 pytest_exit=${PIPESTATUS[0]}
108- echo "unit_failed=$pytest_exit" >> $GITHUB_OUTPUT
109- cat result_unit.log
157+ echo "exit_code=$pytest_exit" >> $GITHUB_OUTPUT
110158 if [ $pytest_exit -ne 0 ]; then
111159 echo "❌ Some unit tests failed"
112160 echo "Failed tests:"
113- grep -E 'FAILED ' result_unit.log || true
161+ grep -E 'FAILED |ERROR ' result_unit.log || true
114162 else
115163 echo "✅ All unit tests passed"
116164 fi
117165
118- # #############################################
119- # SUMMARY & FAIL CONDITIONS
120- # #############################################
166+ - name : Fail job if unit tests failed
167+ if : steps.unit.outputs.exit_code != '0'
168+ shell : bash
169+ run : |
170+ echo "❌ Unit tests failed. See logs above."
171+ exit 1
172+
173+ test-summary :
174+ name : Test Results Summary
175+ runs-on : ubuntu-latest
176+ needs :
177+ - integration-tests
178+ - unit-tests
179+ if : always()
121180
122- - name : Fail workflow if any tests failed
181+ steps :
182+ - name : Print summary and fail when any test job failed
123183 shell : bash
124184 run : |
125- integration_failed ="${{ steps .integration.outputs.integration_failed }}"
126- unit_failed ="${{ steps .unit.outputs.unit_failed }}"
185+ integration_result ="${{ needs .integration-tests.result }}"
186+ unit_result ="${{ needs .unit-tests.result }}"
127187
128188 echo ""
129189 echo "==================== TEST SUMMARY ===================="
130190
131191 any_failed=false
132192
133- if [ "$integration_failed" != "0" ]; then
193+ if [ "$integration_result" = "success" ]; then
194+ echo "✅ Integration tests passed"
195+ else
134196 echo "❌ Integration tests FAILED"
135- echo " → Check the integration test logs above for details."
136- if [ -f result_integration.log ]; then
137- grep -E 'FAILED ' result_integration.log || echo " (No FAILED lines found)"
138- else
139- echo " (Integration log not found)"
140- fi
141197 any_failed=true
142- else
143- echo "✅ Integration tests passed"
144198 fi
145199
146- if [ "$unit_failed" != "0" ]; then
200+ if [ "$unit_result" = "success" ]; then
201+ echo "✅ Unit tests passed"
202+ else
147203 echo "❌ Unit tests FAILED"
148- echo " → Check the unit test logs above for details."
149- if [ -f result_unit.log ]; then
150- grep -E 'FAILED ' result_unit.log || echo " (No FAILED lines found)"
151- else
152- echo " (Unit log not found)"
153- fi
154204 any_failed=true
155- else
156- echo "✅ Unit tests passed"
157205 fi
158206
159207 echo "======================================================"
0 commit comments