TESTME don't MERGE ME #645
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Quarkus CI | |
on: | |
push: | |
branches-ignore: | |
- 'dependabot/**' | |
# paths-ignore in ci-fork-mvn-cache.yml should match | |
paths-ignore: | |
- '.gitignore' | |
- '.dockerignore' | |
- '*.md' | |
- '*.adoc' | |
- '*.txt' | |
- 'adr/**' | |
- 'jakarta/**' | |
- 'docs/src/main/asciidoc/**' | |
- '.github/ISSUE_TEMPLATE/**' | |
- '.github/*.yml' | |
- '.github/*.java' | |
- '.github/*.conf' | |
- '.github/workflows/doc-build.yml' | |
- '.github/workflows/preview.yml' | |
pull_request: | |
types: [opened, synchronize, reopened, ready_for_review] | |
paths-ignore: | |
- '.gitignore' | |
- '.dockerignore' | |
- '*.md' | |
- '*.adoc' | |
- '*.txt' | |
- 'adr/**' | |
- 'jakarta/**' | |
- 'docs/src/main/asciidoc/**' | |
- '.github/ISSUE_TEMPLATE/**' | |
- '.github/*.yml' | |
- '.github/*.java' | |
- '.github/*.conf' | |
- '.github/workflows/doc-build.yml' | |
- '.github/workflows/preview.yml' | |
workflow_dispatch: | |
concurrency: | |
group: "workflow = ${{ github.workflow }}, ref = ${{ github.event.ref }}, pr = ${{ github.event.pull_request.id }}" | |
cancel-in-progress: ${{ github.event_name == 'pull_request' || github.repository != 'quarkusio/quarkus' }} | |
env: | |
# Workaround testsuite locale issue | |
LANG: en_US.UTF-8 | |
COMMON_MAVEN_ARGS: "-e -B --settings .github/mvn-settings.xml --fail-at-end" | |
COMMON_TEST_MAVEN_ARGS: "-Dformat.skip -Denforcer.skip -DskipDocs -Dforbiddenapis.skip -DskipExtensionValidation -DskipCodestartValidation" | |
NATIVE_TEST_MAVEN_ARGS: "-Dtest-containers -Dstart-containers -Dquarkus.native.native-image-xmx=6g -Dnative -Dnative.surefire.skip -Dno-descriptor-tests clean install -DskipDocs" | |
JVM_TEST_MAVEN_ARGS: "-Dtest-containers -Dstart-containers -Dquarkus.test.hang-detection-timeout=60" | |
PTS_MAVEN_ARGS: "-Ddevelocity.pts.enabled=${{ github.event_name == 'pull_request' && github.base_ref == 'main' && 'true' || 'false' }}" | |
DB_USER: hibernate_orm_test | |
DB_PASSWORD: hibernate_orm_test | |
DB_NAME: hibernate_orm_test | |
DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} | |
PULL_REQUEST_NUMBER: ${{ github.event.number }} | |
defaults: | |
run: | |
shell: bash | |
jobs: | |
# This is a hack to work around a GitHub API limitation: | |
# when the PR is coming from another fork, the pull_requests field of the | |
# workflow_run payload is empty. | |
# For more details, see | |
# https://github.community/t/pull-request-attribute-empty-in-workflow-run-event-object-for-pr-from-forked-repo/154682 | |
attach-pr-number: | |
runs-on: ubuntu-latest | |
name: Attach pull request number | |
if: github.event_name == 'pull_request' | |
steps: | |
- name: Create file | |
run: | | |
echo -n ${{ github.event.number }} > pull-request-number | |
- name: Upload pull request number | |
uses: actions/upload-artifact@v4 | |
with: | |
name: pull-request-number-${{ github.event.number }} | |
path: pull-request-number | |
retention-days: 1 | |
ci-sanity-check: | |
name: "CI Sanity Check" | |
runs-on: ubuntu-latest | |
# Skip main in forks | |
if: "github.repository == 'quarkusio/quarkus' || !endsWith(github.ref, '/main')" | |
steps: | |
- name: Build | |
run: sleep 30 | |
build-jdk17: | |
name: "Initial JDK 17 Build" | |
runs-on: ubuntu-latest | |
# Skip main in forks | |
# Skip draft PRs and those with WIP in the subject, rerun as soon as its removed | |
if: "(github.repository == 'quarkusio/quarkus' || !endsWith(github.ref, '/main')) && ( \ | |
github.event_name != 'pull_request' || ( \ | |
github.event.pull_request.draft == false && \ | |
github.event.pull_request.state != 'closed' && \ | |
contains(github.event.pull_request.title, 'wip ') == false && \ | |
contains(github.event.pull_request.title, '[wip]') == false && \ | |
( | |
github.event.action != 'edited' || \ | |
contains(github.event.changes.title.from, 'wip ') || \ | |
contains(github.event.changes.title.from, '[wip]') \ | |
) \ | |
) \ | |
)" | |
outputs: | |
gib_args: ${{ steps.get-gib-args.outputs.gib_args }} | |
gib_impacted: ${{ steps.get-gib-impacted.outputs.impacted_modules }} | |
m2-cache-key: ${{ steps.m2-cache-key.outputs.key }} | |
steps: | |
- name: Gradle Enterprise environment | |
run: | | |
echo "GE_TAGS=jdk-17" >> "$GITHUB_ENV" | |
echo "GE_CUSTOM_VALUES=gh-job-name=Initial JDK 17 Build" >> "$GITHUB_ENV" | |
- uses: actions/checkout@v4 | |
with: | |
# this is important for GIB to work | |
fetch-depth: 0 | |
- name: Add quarkusio remote | |
run: git remote show quarkusio &> /dev/null || git remote add quarkusio https://github.com/quarkusio/quarkus.git | |
- name: Reclaim Disk Space | |
run: .github/ci-prerequisites.sh | |
- name: Set up JDK 17 | |
uses: actions/setup-java@v4 | |
with: | |
distribution: temurin | |
java-version: 17 | |
- name: Generate .m2 cache key | |
id: m2-cache-key | |
run: | | |
echo "key=m2-cache-$(/bin/date -u "+%Y-%U")" >> $GITHUB_OUTPUT | |
- name: Cache Maven Repository | |
id: cache-maven | |
uses: actions/cache@v4 | |
with: | |
path: ~/.m2/repository | |
# refresh cache every week to avoid unlimited growth | |
key: ${{ steps.m2-cache-key.outputs.key }} | |
- name: Verify native-tests.json | |
run: ./.github/verify-tests-json.sh native-tests.json integration-tests/ | |
- name: Verify virtual-threads-tests.json | |
run: ./.github/verify-tests-json.sh virtual-threads-tests.json integration-tests/virtual-threads/ | |
- name: Setup Develocity Build Scan capture | |
uses: gradle/develocity-actions/maven-setup@v1 | |
with: | |
capture-strategy: ON_DEMAND | |
job-name: "Initial JDK 17 Build" | |
add-pr-comment: false | |
add-job-summary: false | |
- name: Build | |
env: | |
CAPTURE_BUILD_SCAN: true | |
run: | | |
./mvnw -T1C $COMMON_MAVEN_ARGS -DskipTests -DskipITs -DskipDocs -Dinvoker.skip -Dskip.gradle.tests -Djbang.skip -Dtruststore.skip -Dno-format -Dtcks -Prelocations clean install | |
- name: Verify extension dependencies | |
run: ./update-extension-dependencies.sh $COMMON_MAVEN_ARGS | |
- name: Get GIB arguments | |
id: get-gib-args | |
env: | |
PULL_REQUEST_BASE: ${{ github.event.pull_request.base.ref }} | |
run: | | |
# See also: https://github.com/gitflow-incremental-builder/gitflow-incremental-builder#configuration (GIB) | |
# Common GIB_ARGS for all CI cases (hint: see also root pom.xml): | |
# - disableSelectedProjectsHandling: required to detect changes in jobs that use -pl | |
# - untracked: to ignore files created by jobs (and uncommitted to be consistent) | |
GIB_ARGS="-Dincremental -Dgib.disableSelectedProjectsHandling -Dgib.untracked=false -Dgib.uncommitted=false" | |
if [ -n "$PULL_REQUEST_BASE" ] | |
then | |
# The PR defines a clear merge target so just use that branch for reference, *unless*: | |
# - the current branch is a backport branch targeting some released branch like 1.10 (merge target is not main) | |
GIB_ARGS+=" -Dgib.referenceBranch=origin/$PULL_REQUEST_BASE -Dgib.disableIfReferenceBranchMatches='origin/\d+\.\d+'" | |
else | |
# No PR means the merge target is uncertain so fetch & use main of quarkusio/quarkus, *unless*: | |
# - the current branch is main or some released branch like 1.10 | |
# - the current branch is a backport branch which is going to target some released branch like 1.10 (merge target is not main) | |
GIB_ARGS+=" -Dgib.referenceBranch=refs/remotes/quarkusio/main -Dgib.fetchReferenceBranch -Dgib.disableIfBranchMatches='main|\d+\.\d+|.*backport.*'" | |
fi | |
echo "GIB_ARGS: $GIB_ARGS" | |
echo "gib_args=${GIB_ARGS}" >> $GITHUB_OUTPUT | |
- name: Get GIB impacted modules | |
id: get-gib-impacted | |
# mvnw just for creating gib-impacted.log ("validate" should not waste much time if not incremental at all, e.g. on main) | |
run: | | |
./mvnw -q -T1C $COMMON_MAVEN_ARGS -Dscan=false -Dtcks -Dquickly-ci ${{ steps.get-gib-args.outputs.gib_args }} -Dgib.logImpactedTo=gib-impacted.log validate | |
if [ -f gib-impacted.log ] | |
then | |
GIB_IMPACTED=$(cat gib-impacted.log) | |
else | |
GIB_IMPACTED='_all_' | |
fi | |
echo "GIB_IMPACTED: ${GIB_IMPACTED}" | |
# three steps to retain linefeeds in output for other jobs | |
# (see https://github.com/github/docs/issues/21529 and https://github.com/orgs/community/discussions/26288#discussioncomment-3876281) | |
echo 'impacted_modules<<EOF' >> $GITHUB_OUTPUT | |
echo "${GIB_IMPACTED}" >> $GITHUB_OUTPUT | |
echo 'EOF' >> $GITHUB_OUTPUT | |
- name: Tar .m2/repository/io/quarkus | |
run: tar -czf m2-io-quarkus.tgz -C ~ .m2/repository/io/quarkus | |
- name: Upload .m2/repository/io/quarkus | |
uses: actions/upload-artifact@v4 | |
with: | |
name: m2-io-quarkus | |
path: m2-io-quarkus.tgz | |
retention-days: 7 | |
- name: Delete snapshots artifacts from cache | |
run: find ~/.m2 -name \*-SNAPSHOT -type d -exec rm -rf {} + | |
- name: Prepare build reports archive | |
if: always() | |
run: | | |
7z a -tzip build-reports.zip -r \ | |
'target/build-report.json' \ | |
'target/gradle-build-scan-url.txt' \ | |
LICENSE | |
- name: Upload build reports | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: "build-reports-Initial JDK 17 Build" | |
path: | | |
build-reports.zip | |
retention-days: 7 | |
calculate-test-jobs: | |
name: Calculate Test Jobs | |
runs-on: ubuntu-latest | |
# Skip main in forks | |
if: "github.repository == 'quarkusio/quarkus' || !endsWith(github.ref, '/main')" | |
needs: build-jdk17 | |
env: | |
GIB_IMPACTED_MODULES: ${{ needs.build-jdk17.outputs.gib_impacted }} | |
outputs: | |
native_matrix: ${{ steps.calc-native-matrix.outputs.matrix }} | |
jvm_matrix: ${{ steps.calc-jvm-matrix.outputs.matrix }} | |
virtual_threads_matrix: ${{ steps.calc-virtual-threads-matrix.outputs.matrix }} | |
run_jvm: ${{ steps.calc-run-flags.outputs.run_jvm }} | |
run_devtools: ${{ steps.calc-run-flags.outputs.run_devtools }} | |
run_gradle: ${{ steps.calc-run-flags.outputs.run_gradle }} | |
run_maven: ${{ steps.calc-run-flags.outputs.run_maven }} | |
run_kubernetes: ${{ steps.calc-run-flags.outputs.run_kubernetes }} | |
run_quickstarts: ${{ steps.calc-run-flags.outputs.run_quickstarts }} | |
run_tcks: ${{ steps.calc-run-flags.outputs.run_tcks }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Calculate matrix from native-tests.json | |
id: calc-native-matrix | |
run: | | |
echo "GIB_IMPACTED_MODULES: ${GIB_IMPACTED_MODULES}" | |
json=$(.github/filter-native-tests-json.sh "${GIB_IMPACTED_MODULES}" | tr -d '\n') | |
echo "${json}" | |
echo "matrix=${json}" >> $GITHUB_OUTPUT | |
- name: Calculate matrix from matrix-jvm-tests.json | |
id: calc-jvm-matrix | |
run: | | |
json=$(.github/filter-jvm-tests-json.sh) | |
echo "${json}" | |
echo "matrix=${json}" >> $GITHUB_OUTPUT | |
- name: Calculate matrix from virtual-threads-tests.json | |
id: calc-virtual-threads-matrix | |
run: | | |
echo "GIB_IMPACTED_MODULES: ${GIB_IMPACTED_MODULES}" | |
json=$(.github/filter-virtual-threads-tests-json.sh "${GIB_IMPACTED_MODULES}" | tr -d '\n') | |
echo "${json}" | |
echo "matrix=${json}" >> $GITHUB_OUTPUT | |
- name: Calculate run flags | |
id: calc-run-flags | |
run: | | |
run_jvm=true; run_devtools=true; run_gradle=true; run_maven=true; run_kubernetes=true; run_quickstarts=true; run_tcks=true | |
if [ -z "${GIB_IMPACTED_MODULES}" ] | |
then | |
run_jvm=false; run_devtools=false; run_gradle=false; run_maven=false; run_kubernetes=false; run_quickstarts=false; run_tcks=false | |
elif [ "${GIB_IMPACTED_MODULES}" != '_all_' ] | |
then | |
# Important: keep -pl ... in actual jobs in sync with the following grep commands! | |
if ! echo -n "${GIB_IMPACTED_MODULES}" | grep -qPv 'integration-tests/(devtools|gradle|maven|devmode|kubernetes/.*)|tcks/.*'; then run_jvm=false; fi | |
if ! echo -n "${GIB_IMPACTED_MODULES}" | grep -q 'integration-tests/devtools'; then run_devtools=false; fi | |
if ! echo -n "${GIB_IMPACTED_MODULES}" | grep -q 'integration-tests/gradle'; then run_gradle=false; fi | |
if ! echo -n "${GIB_IMPACTED_MODULES}" | grep -qP 'integration-tests/(maven|devmode)'; then run_maven=false; fi | |
if ! echo -n "${GIB_IMPACTED_MODULES}" | grep -qP 'integration-tests/kubernetes/.*'; then run_kubernetes=false; fi | |
if ! echo -n "${GIB_IMPACTED_MODULES}" | grep -qPv '(docs|integration-tests|tcks)/.*'; then run_quickstarts=false; fi | |
if ! echo -n "${GIB_IMPACTED_MODULES}" | grep -q 'tcks/.*'; then run_tcks=false; fi | |
fi | |
echo "run_jvm=${run_jvm}, run_devtools=${run_devtools}, run_gradle=${run_gradle}, run_maven=${run_maven}, run_kubernetes=${run_kubernetes}, run_quickstarts=${run_quickstarts}, run_tcks=${run_tcks}" | |
echo "run_jvm=${run_jvm}" >> $GITHUB_OUTPUT | |
echo "run_devtools=${run_devtools}" >> $GITHUB_OUTPUT | |
echo "run_gradle=${run_gradle}" >> $GITHUB_OUTPUT | |
echo "run_maven=${run_maven}" >> $GITHUB_OUTPUT | |
echo "run_kubernetes=${run_kubernetes}" >> $GITHUB_OUTPUT | |
echo "run_quickstarts=${run_quickstarts}" >> $GITHUB_OUTPUT | |
echo "run_tcks=${run_tcks}" >> $GITHUB_OUTPUT | |
native-tests: | |
name: Native Tests - ${{matrix.category}} | |
needs: [build-jdk17, calculate-test-jobs] | |
runs-on: ${{matrix.os-name}} | |
env: | |
# leave more space for the actual native compilation and execution | |
MAVEN_OPTS: -Xmx1g | |
# Skip main in forks | |
if: "needs.calculate-test-jobs.outputs.native_matrix != '{}' && (github.repository == 'quarkusio/quarkus' || !endsWith(github.ref, '/main'))" | |
# Ignore the following YAML Schema error | |
timeout-minutes: ${{matrix.timeout}} | |
strategy: | |
max-parallel: 12 | |
fail-fast: false | |
matrix: ${{ fromJson(needs.calculate-test-jobs.outputs.native_matrix) }} | |
steps: | |
- name: Gradle Enterprise environment | |
run: | | |
category=$(echo -n '${{matrix.category}}' | tr '[:upper:]' '[:lower:]' | tr -c '[:alnum:]-' '-' | sed -E 's/-+/-/g') | |
echo "GE_TAGS=native-${category}" >> "$GITHUB_ENV" | |
echo "GE_CUSTOM_VALUES=gh-job-name=Native Tests - ${{matrix.category}}" >> "$GITHUB_ENV" | |
- name: Support longpaths on Windows | |
if: "startsWith(matrix.os-name, 'windows')" | |
run: git config --global core.longpaths true | |
- uses: actions/checkout@v4 | |
- name: Reclaim Disk Space | |
run: .github/ci-prerequisites.sh | |
if: ${{ !startsWith(matrix.os-name, 'windows') }} | |
- name: Set up JDK 17 | |
uses: actions/setup-java@v4 | |
with: | |
distribution: temurin | |
java-version: 17 | |
- name: Install cl.exe | |
if: startsWith(matrix.os-name, 'windows') | |
uses: ilammy/msvc-dev-cmd@v1 | |
- uses: microsoft/setup-msbuild@v2 | |
if: startsWith(matrix.os-name, 'windows') | |
- name: Setup GraalVM | |
id: setup-graalvm | |
uses: graalvm/setup-graalvm@v1 | |
if: startsWith(matrix.os-name, 'windows') | |
with: | |
version: 'mandrel-latest' | |
java-version: '21' | |
distribution: 'mandrel' | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
# We do this so we can get better analytics for the downloaded version of the build images | |
- name: Update Docker Client User Agent | |
run: | | |
if [ -f ~/.docker/config.json ]; then | |
cat <<< $(jq '.HttpHeaders += {"User-Agent": "Quarkus-CI-Docker-Client"}' ~/.docker/config.json) > ~/.docker/config.json | |
fi | |
- name: Restore Maven Repository | |
uses: actions/cache/restore@v4 | |
with: | |
path: ~/.m2/repository | |
# refresh cache every week to avoid unlimited growth | |
key: ${{ needs.build-jdk17.outputs.m2-cache-key }} | |
- name: Download .m2/repository/io/quarkus | |
uses: actions/download-artifact@v4 | |
with: | |
name: m2-io-quarkus | |
path: . | |
- name: Extract .m2/repository/io/quarkus | |
run: tar -xzf m2-io-quarkus.tgz -C ~ | |
- name: Setup Develocity Build Scan capture | |
uses: gradle/develocity-actions/maven-setup@v1 | |
with: | |
capture-strategy: ON_DEMAND | |
job-name: "Native Tests - ${{matrix.category}}" | |
add-pr-comment: false | |
add-job-summary: false | |
- name: Cache Quarkus metadata | |
uses: actions/cache@v4 | |
with: | |
path: '**/.quarkus/quarkus-prod-config-dump' | |
key: ${{ runner.os }}-quarkus-metadata | |
- name: Build | |
env: | |
TEST_MODULES: ${{matrix.test-modules}} | |
CONTAINER_BUILD: ${{startsWith(matrix.os-name, 'windows') && 'false' || 'true'}} | |
CAPTURE_BUILD_SCAN: true | |
run: ./mvnw $COMMON_MAVEN_ARGS $COMMON_TEST_MAVEN_ARGS $PTS_MAVEN_ARGS -f integration-tests -pl "$TEST_MODULES" $NATIVE_TEST_MAVEN_ARGS -Dquarkus.native.container-build=$CONTAINER_BUILD | |
- name: Prepare failure archive (if maven failed) | |
if: failure() | |
run: find . -type d -name '*-reports' -o -wholename '*/build/reports/tests/functionalTest' -o -name '*.log' | tar -czf test-reports.tgz -T - | |
- name: Upload failure Archive (if maven failed) | |
uses: actions/upload-artifact@v4 | |
if: failure() | |
with: | |
name: test-reports-native-${{matrix.category}} | |
path: 'test-reports.tgz' | |
retention-days: 7 | |
- name: Prepare build reports archive | |
if: always() | |
run: | | |
7z a -tzip build-reports.zip -r \ | |
'**/target/*-reports/TEST-*.xml' \ | |
'**/build/test-results/test/TEST-*.xml' \ | |
'target/build-report.json' \ | |
'target/gradle-build-scan-url.txt' \ | |
LICENSE | |
- name: Upload build reports | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: "build-reports-Native Tests - ${{matrix.category}}" | |
path: | | |
build-reports.zip | |
retention-days: 7 | |
- name: Collect build JSON stats | |
shell: bash | |
run: find . -name '*runner*.json' | tar czvf build-stats.tgz -T - | |
- name: Upload build JSON stats | |
uses: actions/upload-artifact@v4 | |
with: | |
name: build-stats-${{matrix.category}} | |
path: 'build-stats.tgz' | |
retention-days: 7 | |
native-tests-stats-upload: | |
name: Upload build stats to collector | |
# if: ${{ always() && github.repository == 'quarkusio/quarkus' && endsWith(github.ref, '/main') && github.event_name != 'pull_request' && needs.native-tests.result != 'skipped' && needs.native-tests.result != 'cancelled' }} | |
needs: | |
- native-tests | |
- calculate-test-jobs | |
strategy: | |
fail-fast: false | |
matrix: ${{ fromJson(needs.calculate-test-jobs.outputs.native_matrix) }} | |
runs-on: ${{matrix.os-name}} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
repository: graalvm/mandrel | |
fetch-depth: 1 | |
path: workflow-quarkus | |
- uses: actions/download-artifact@v4 | |
with: | |
name: build-stats-${{matrix.category}} | |
path: . | |
- name: Extract and import build stats | |
env: | |
UPLOAD_TOKEN: ${{ secrets.UPLOAD_COLLECTOR_TOKEN }} | |
COLLECTOR_URL: https://stage-collector.foci.life/api/v1/image-stats | |
TAG: quarkus-main-ci | |
shell: bash | |
run: | | |
tar -xf build-stats.tgz | |
echo "Tag for stat upload is going to be: '${TAG}'" | |
for bs in $(find ./quarkus/ -name \*build-output-stats.json); do | |
f=$(echo "$bs" | sed 's/\(.*\)-build-output-stats\.json/\1/g') | |
d=$(dirname $bs) | |
# import the stat | |
stat_id=$(curl -s -w '\n' -H "Content-Type: application/json" \ | |
-H "token: $UPLOAD_TOKEN" --post302 --data "@$(pwd)/$bs" "$URL/import?t=$TAG" | jq .id) | |
echo "Imported stat id: $stat_id" | |
# Create runner info json | |
cat > ./runner-info.json <<EOF | |
{ | |
"testVersion": "$GITHUB_REF_NAME", | |
"mandrelVersion": null, | |
"quarkusVersion": "@GITHUB_SHA", | |
"jdkVersion": "$(java -version)", | |
"operatingSystem": "$RUNNER_OS", | |
"architecture": "$RUNNER_ARCH", | |
"memorySizeBytes": "$(free -b | awk '/Mem:/{print $2}')", | |
"memorySizeAvailableBytes": "$(free -b | awk '/Mem:/{print $4}')", | |
"description": "Quarkus CI github runner on $GITHUB_REF_NAME branch/tag", | |
} | |
EOF | |
jq . runner-info.json | |
# Add runner info | |
curl -s -w '\n' -H "Content-Type: application/json" -H "token: $TOKEN" \ | |
-X PUT --data "@./runner-info.json" "$COLLECTOR_URL/update-runner-info/$stat_id" > /dev/null | |
done | |