Skip to content

Commit 8cc8eea

Browse files
committed
migrate ci from buildkite to workflow
1 parent ba73305 commit 8cc8eea

9 files changed

Lines changed: 417 additions & 53 deletions

File tree

.github/workflows/pr-check.yml

Lines changed: 289 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -93,53 +93,17 @@ jobs:
9393
core.info('PR lint passed.');
9494
}
9595
96-
build:
97-
name: Build (JDK ${{ matrix.java }} / ${{ matrix.arch }})
98-
needs: pr-lint
99-
runs-on: ${{ matrix.runner }}
100-
strategy:
101-
fail-fast: false
102-
matrix:
103-
include:
104-
- java: '8'
105-
runner: ubuntu-latest
106-
arch: x86_64
107-
- java: '17'
108-
runner: ubuntu-24.04-arm
109-
arch: aarch64
110-
111-
steps:
112-
- uses: actions/checkout@v4
113-
114-
- name: Set up JDK ${{ matrix.java }}
115-
uses: actions/setup-java@v4
116-
with:
117-
java-version: ${{ matrix.java }}
118-
distribution: 'temurin'
119-
120-
- name: Cache Gradle packages
121-
uses: actions/cache@v4
122-
with:
123-
path: |
124-
~/.gradle/caches
125-
~/.gradle/wrapper
126-
key: ${{ runner.os }}-${{ matrix.arch }}-gradle-${{ hashFiles('**/*.gradle', '**/gradle-wrapper.properties') }}
127-
restore-keys: ${{ runner.os }}-${{ matrix.arch }}-gradle-
128-
129-
- name: Build
130-
run: ./gradlew clean build -x test
131-
13296
checkstyle:
13397
name: Checkstyle
134-
runs-on: ubuntu-latest
98+
runs-on: ubuntu-24.04-arm
13599

136100
steps:
137101
- uses: actions/checkout@v4
138102

139-
- name: Set up JDK 8
103+
- name: Set up JDK 17
140104
uses: actions/setup-java@v4
141105
with:
142-
java-version: '8'
106+
java-version: '17'
143107
distribution: 'temurin'
144108

145109
- name: Cache Gradle packages
@@ -163,20 +127,29 @@ jobs:
163127
framework/build/reports/checkstyle/
164128
plugins/build/reports/checkstyle/
165129
166-
test:
167-
name: Unit Tests (JDK ${{ matrix.java }} / ${{ matrix.arch }})
130+
build:
131+
name: Build ${{ matrix.os-name }}(JDK ${{ matrix.java }} / ${{ matrix.arch }})
132+
needs: [pr-lint, checkstyle]
168133
runs-on: ${{ matrix.runner }}
169-
needs: build
170-
timeout-minutes: 60
171134
strategy:
172135
fail-fast: false
173136
matrix:
174137
include:
175138
- java: '8'
176139
runner: ubuntu-latest
140+
os-name: ubuntu
177141
arch: x86_64
178142
- java: '17'
179143
runner: ubuntu-24.04-arm
144+
os-name: ubuntu
145+
arch: aarch64
146+
- java: '8'
147+
runner: macos-26-intel
148+
os-name: macos
149+
arch: x86_64
150+
- java: '17'
151+
runner: macos-latest
152+
os-name: macos
180153
arch: aarch64
181154

182155
steps:
@@ -197,13 +170,280 @@ jobs:
197170
key: ${{ runner.os }}-${{ matrix.arch }}-gradle-${{ hashFiles('**/*.gradle', '**/gradle-wrapper.properties') }}
198171
restore-keys: ${{ runner.os }}-${{ matrix.arch }}-gradle-
199172

200-
- name: Run tests
201-
run: ./gradlew test
173+
- name: Build
174+
run: ./gradlew clean build --no-daemon
175+
176+
docker-build-rockylinux:
177+
name: Build rockylinux (JDK 8 / x86_64)
178+
needs: [pr-lint, checkstyle]
179+
runs-on: ubuntu-latest
180+
181+
container:
182+
image: rockylinux:8
202183

203-
- name: Upload test reports
204-
if: failure()
184+
env:
185+
GRADLE_USER_HOME: /github/home/.gradle
186+
LANG: en_US.UTF-8
187+
LC_ALL: en_US.UTF-8
188+
189+
steps:
190+
- name: Checkout code
191+
uses: actions/checkout@v4
192+
193+
- name: Install dependencies (Rocky 8 + JDK8)
194+
run: |
195+
set -euxo pipefail
196+
dnf -y install java-1.8.0-openjdk-devel git wget unzip which jq bc curl glibc-langpack-en
197+
dnf -y groupinstall "Development Tools"
198+
199+
- name: Check Java version
200+
run: java -version
201+
202+
- name: Cache Gradle
203+
uses: actions/cache@v4
204+
with:
205+
path: |
206+
/github/home/.gradle/caches
207+
/github/home/.gradle/wrapper
208+
key: ${{ runner.os }}-rockylinux-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
209+
restore-keys: |
210+
${{ runner.os }}-rockylinux-gradle-
211+
212+
- name: Prepare checkstyle config copy
213+
run: |
214+
set -euxo pipefail
215+
cp -f config/checkstyle/checkStyle.xml config/checkstyle/checkStyleAll.xml || true
216+
217+
- name: Grant execute permission
218+
run: chmod +x gradlew
219+
220+
- name: Stop Gradle daemon
221+
run: ./gradlew --stop || true
222+
223+
- name: Build
224+
run: ./gradlew clean build --no-daemon --no-build-cache
225+
#run: |
226+
# ./gradlew clean build -x test --no-daemon --no-build-cache
227+
# ./gradlew framework:test --tests org.tron.core.zksnark.ShieldedReceiveTest
228+
229+
- name: Generate JaCoCo report
230+
run: ./gradlew jacocoTestReport --no-daemon --no-build-cache
231+
232+
- name: Upload JaCoCo artifacts
205233
uses: actions/upload-artifact@v4
206234
with:
207-
name: test-reports-${{ matrix.arch }}
235+
name: jacoco-rockylinux
208236
path: |
209-
**/build/reports/tests/
237+
**/build/reports/jacoco/test/jacocoTestReport.xml
238+
**/build/reports/**
239+
**/build/test-results/**
240+
if-no-files-found: error
241+
242+
docker-build-debian11:
243+
name: Build debian11 (JDK 8 / x86_64)
244+
needs: [pr-lint, checkstyle]
245+
runs-on: ubuntu-latest
246+
247+
container:
248+
image: eclipse-temurin:8-jdk # base image is Debian 11 (Bullseye)
249+
250+
defaults:
251+
run:
252+
shell: bash
253+
254+
env:
255+
GRADLE_USER_HOME: /github/home/.gradle
256+
257+
steps:
258+
- name: Checkout code
259+
uses: actions/checkout@v4
260+
261+
- name: Install dependencies (Debian + build tools)
262+
run: |
263+
set -euxo pipefail
264+
apt-get update
265+
apt-get install -y git wget unzip build-essential curl jq
266+
267+
- name: Check Java version
268+
run: java -version
269+
270+
- name: Cache Gradle
271+
uses: actions/cache@v4
272+
with:
273+
path: |
274+
/github/home/.gradle/caches
275+
/github/home/.gradle/wrapper
276+
key: ${{ runner.os }}-debian11-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
277+
restore-keys: |
278+
${{ runner.os }}-debian11-gradle-
279+
280+
- name: Grant execute permission
281+
run: chmod +x gradlew
282+
283+
- name: Build
284+
run: ./gradlew clean build --no-daemon --no-build-cache
285+
286+
287+
coverage-gate:
288+
name: Coverage Gate (from rockylinux build)
289+
needs: docker-build-rockylinux
290+
runs-on: ubuntu-latest
291+
292+
permissions:
293+
contents: read
294+
295+
defaults:
296+
run:
297+
shell: bash
298+
299+
steps:
300+
- name: Checkout code (needed by codecov-action for git context)
301+
uses: actions/checkout@v4
302+
303+
- name: Download JaCoCo artifacts (rockylinux)
304+
uses: actions/download-artifact@v4
305+
with:
306+
name: jacoco-rockylinux
307+
path: artifacts/jacoco-rockylinux
308+
309+
- name: List downloaded reports
310+
run: |
311+
set -eux
312+
echo "JaCoCo XML reports found:"
313+
find artifacts/jacoco-rockylinux -name jacocoTestReport.xml
314+
315+
- name: Upload coverage to Codecov
316+
uses: codecov/codecov-action@v5
317+
with:
318+
token: ${{ secrets.CODECOV_TOKEN }}
319+
directory: artifacts/jacoco-rockylinux
320+
override_commit: ${{ github.event.pull_request.head.sha }}
321+
override_branch: ${{ github.event.pull_request.head.ref }}
322+
override_pr: ${{ github.event.pull_request.number }}
323+
verbose: true
324+
fail_ci_if_error: true
325+
326+
- name: Install tools
327+
run: sudo apt-get update && sudo apt-get install -y jq bc curl
328+
329+
- name: Wait for Codecov processing
330+
env:
331+
CODECOV_API_TOKEN: ${{ secrets.CODECOV_API_TOKEN }}
332+
CODECOV_OWNER: ${{ github.repository_owner }}
333+
CODECOV_REPO: ${{ github.event.repository.name }}
334+
COMMIT_ID: ${{ github.event.pull_request.head.sha }}
335+
run: |
336+
set -euxo pipefail
337+
338+
API_URL="https://api.codecov.io/api/v2/github/${CODECOV_OWNER}/repos/${CODECOV_REPO}/commits/${COMMIT_ID}"
339+
MAX_ATTEMPTS=20
340+
INTERVAL=30
341+
342+
for i in $(seq 1 $MAX_ATTEMPTS); do
343+
echo "=== Polling attempt $i / $MAX_ATTEMPTS ==="
344+
345+
http_code=$(curl -sS -o /tmp/poll.json -w '%{http_code}' \
346+
-H "Authorization: Bearer ${CODECOV_API_TOKEN}" \
347+
"$API_URL")
348+
349+
if [ "$http_code" = "200" ]; then
350+
state=$(jq -r '.state // "unknown"' /tmp/poll.json)
351+
echo "Commit processing state: $state"
352+
if [ "$state" = "complete" ]; then
353+
echo "Codecov has finished processing."
354+
exit 0
355+
fi
356+
else
357+
echo "HTTP $http_code — commit not yet available."
358+
cat /tmp/poll.json 2>/dev/null || true
359+
fi
360+
361+
if [ "$i" -lt "$MAX_ATTEMPTS" ]; then
362+
sleep "$INTERVAL"
363+
fi
364+
done
365+
366+
echo "Timed out waiting for Codecov (${MAX_ATTEMPTS} x ${INTERVAL}s)."
367+
exit 1
368+
369+
- name: Coverage gate via Codecov REST API
370+
env:
371+
CODECOV_API_TOKEN: ${{ secrets.CODECOV_API_TOKEN }}
372+
CODECOV_OWNER: ${{ github.repository_owner }}
373+
CODECOV_REPO: ${{ github.event.repository.name }}
374+
COMMIT_ID: ${{ github.event.pull_request.head.sha }}
375+
BASE_BRANCH: ${{ github.event.pull_request.base.ref }}
376+
PR_NUMBER: ${{ github.event.pull_request.number }}
377+
run: |
378+
set -euxo pipefail
379+
380+
API_BASE="https://api.codecov.io/api/v2/github/${CODECOV_OWNER}/repos/${CODECOV_REPO}"
381+
AUTH="Authorization: Bearer ${CODECOV_API_TOKEN}"
382+
383+
# Helper: GET with error handling
384+
api_get() {
385+
local url="$1"
386+
local http_code
387+
http_code=$(curl -sS -o /tmp/api_out.json -w '%{http_code}' \
388+
-H "$AUTH" "$url")
389+
if [ "$http_code" != "200" ]; then
390+
echo "ERROR: GET $url => HTTP $http_code" >&2
391+
cat /tmp/api_out.json >&2
392+
return 1
393+
fi
394+
cat /tmp/api_out.json
395+
}
396+
397+
# 1) Current commit coverage
398+
echo "=== 1. Current commit coverage (sha: ${COMMIT_ID}) ==="
399+
commit_resp=$(api_get "${API_BASE}/totals/?sha=${COMMIT_ID}")
400+
self_cov=$(echo "$commit_resp" | jq -r '.totals.coverage // 0')
401+
echo "self_cov = ${self_cov}%"
402+
403+
# 2) Base branch head coverage
404+
echo "=== 2. Base branch coverage (branch: ${BASE_BRANCH}) ==="
405+
base_resp=$(api_get "${API_BASE}/totals/?branch=${BASE_BRANCH}")
406+
base_branch_cov=$(echo "$base_resp" | jq -r '.totals.coverage // 0')
407+
echo "base_branch_cov = ${base_branch_cov}%"
408+
409+
# 3) PR comparison — patch coverage
410+
echo "=== 3. PR #${PR_NUMBER} comparison ==="
411+
compare_resp=$(api_get "${API_BASE}/compare/?pullid=${PR_NUMBER}")
412+
patch_cov=$(echo "$compare_resp" | jq -r '.totals.patch.coverage // 0')
413+
impacted_files=$(echo "$compare_resp" | jq -r '(.files // []) | length')
414+
echo "patch_cov = ${patch_cov}%"
415+
echo "impacted_files = ${impacted_files}"
416+
417+
# ===== Gate Rules =====
418+
419+
# Rule 1: current commit must have valid coverage
420+
if [ "$(echo "$self_cov <= 0" | bc)" -eq 1 ]; then
421+
echo "FAIL: Could not retrieve valid coverage for commit ${COMMIT_ID}."
422+
exit 1
423+
fi
424+
425+
# Rule 2: overall coverage must not decrease vs base branch
426+
if [ "$(echo "$self_cov < $base_branch_cov" | bc)" -eq 1 ]; then
427+
echo "FAIL: Overall coverage decreased!"
428+
echo " Current commit : ${self_cov}%"
429+
echo " Base branch : ${base_branch_cov}%"
430+
echo "Please add unit tests to maintain coverage."
431+
exit 1
432+
fi
433+
434+
# Rule 3: patch coverage on changed files >= 80%
435+
# if [ "$impacted_files" -gt 0 ] && [ "$(echo "$patch_cov > 0" | bc)" -eq 1 ]; then
436+
# if [ "$(echo "$patch_cov < 80" | bc)" -eq 1 ]; then
437+
# echo "FAIL: Patch coverage is ${patch_cov}% (minimum 80%)."
438+
# echo "Please add tests for new/changed code."
439+
# exit 1
440+
# fi
441+
# else
442+
# echo "No impacted files or no patch data; skipping patch coverage check."
443+
# fi
444+
445+
echo ""
446+
echo "All coverage gates passed!"
447+
echo " Current commit : ${self_cov}%"
448+
echo " Base branch : ${base_branch_cov}%"
449+
echo " Patch coverage : ${patch_cov}%"

0 commit comments

Comments
 (0)