diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2c9f1954e..5a3e53a24 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,4 @@ * @oracle/graalvm-reachability-maintainer tests/tck-build-logic/src/main/resources/allowed-docker-images/* @matneu @matteoldani library-and-framework-list.json @fniephaus +.github/* @vjovanov diff --git a/.github/workflows/check-new-library-versions.yml b/.github/workflows/check-new-library-versions.yml deleted file mode 100644 index e012911d4..000000000 --- a/.github/workflows/check-new-library-versions.yml +++ /dev/null @@ -1,168 +0,0 @@ -name: "Check new library versions" - -# The workflow runs bi-weekly alternating with the scheduled release workflow. This way we have enough time to provide metadata for failing tests. -# In case we need more scans, there is a possibility to trigger the workflow manually. -on: - schedule: - - cron: "0 0 8 * *" - - cron: "0 0 22 * *" - workflow_dispatch: - -permissions: - contents: write - actions: write - -concurrency: - group: "workflow = ${{ github.workflow }}, ref = ${{ github.event.ref }}, pr = ${{ github.event.pull_request.id }}" - cancel-in-progress: true - -jobs: - get-all-libraries: - if: github.repository == 'oracle/graalvm-reachability-metadata' - name: "πŸ“‹ Get list of all supported libraries with newer versions" - permissions: write-all - runs-on: "ubuntu-22.04" - timeout-minutes: 5 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - - name: "☁️ Checkout repository" - uses: actions/checkout@v4 - - name: "πŸ”§ Prepare environment" - uses: graalvm/setup-graalvm@v1 - with: - java-version: '21' - distribution: 'graalvm' - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: "πŸ•ΈοΈ Populate matrix" - id: set-matrix - run: | - ./gradlew fetchExistingLibrariesWithNewerVersions --matrixLimit=200 - - name: "πŸ”¨ Create branch" - run: | - git config --local user.email "actions@github.com" - git config --local user.name "Github Actions" - git switch -C check-new-library-versions/$(date '+%Y-%m-%d') - git push origin check-new-library-versions/$(date '+%Y-%m-%d') - - test-all-metadata: - name: "πŸ§ͺ ${{ matrix.coordinates }} (GraalVM for JDK ${{ matrix.version }} @ ${{ matrix.os }})" - permissions: write-all - runs-on: ${{ matrix.os }} - timeout-minutes: 20 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - needs: get-all-libraries - strategy: - fail-fast: false - matrix: ${{ fromJson(needs.get-all-libraries.outputs.matrix) }} - steps: - - name: "☁️ Checkout repository" - uses: actions/checkout@v4 - - name: "πŸ”§ Setup java" - uses: actions/setup-java@v4 - with: - distribution: 'oracle' - java-version: '21' - - name: "πŸ”§ Prepare environment" - uses: graalvm/setup-graalvm@v1 - with: - set-java-home: 'false' - java-version: ${{ matrix.version }} - distribution: 'graalvm' - github-token: ${{ secrets.GITHUB_TOKEN }} - native-image-job-reports: 'true' - - name: "Extract test path and library version" - run: | - LIBRARY_PATH=$(echo ${{ matrix.coordinates }} | cut -d ':' -f1-2 | sed 's/:/\//g') - LATEST_VERSION=$(find tests/src/$LIBRARY_PATH/* -maxdepth 1 -type d | sort -V | tail -1 | cut -d '/' -f5) - TEST_PATH="$LIBRARY_PATH/$LATEST_VERSION" - TEST_COORDINATES=$(echo "$TEST_PATH" | tr / :) - - echo "LATEST_VERSION=$LATEST_VERSION" >> ${GITHUB_ENV} - echo "TEST_PATH=$TEST_PATH" >> ${GITHUB_ENV} - echo "TEST_COORDINATES=$TEST_COORDINATES" >> ${GITHUB_ENV} - - name: "Pull allowed docker images" - run: | - ./gradlew pullAllowedDockerImages --coordinates=${{ env.TEST_COORDINATES }} - - name: "Disable docker" - run: | - sudo apt-get install openbsd-inetd - sudo bash -c "cat ./.github/workflows/discard-port.conf >> /etc/inetd.conf" - sudo systemctl start inetd - sudo mkdir /etc/systemd/system/docker.service.d - sudo bash -c "cat ./.github/workflows/dockerd.service > /etc/systemd/system/docker.service.d/http-proxy.conf" - sudo systemctl daemon-reload - sudo systemctl restart docker - - name: "πŸ§ͺ Run '${{ env.TEST_COORDINATES }}' tests" - run: | - TESTING_VERSION=$(echo ${{ matrix.coordinates }} | cut -d ":" -f3) - export GVM_TCK_LV=$TESTING_VERSION - - ./gradlew test -Pcoordinates=${{ env.TEST_COORDINATES }} - - name: "βœ”οΈ New library is supported" - if: success() - run: | - bash ./.github/workflows/tryPushVersionsUpdate.sh ${{ matrix.coordinates }} ${{ env.LATEST_VERSION }} - - name: "❗ New library is not supported" - if: failure() - run: | - LIB=$(echo "${{ matrix.coordinates }}" | sed 's/:/_/g') - touch $LIB - echo "UNSUPPORTED_LIB=$LIB" >> $GITHUB_ENV - - name: "Upload artifacts" - if: failure() - id: upload - continue-on-error: true - uses: actions/upload-artifact@v4 - with: - name: ${{ env.UNSUPPORTED_LIB }} - path: ${{ env.UNSUPPORTED_LIB }} - retention-days: 1 - - process-results: - name: "πŸ§ͺ Process results" - runs-on: "ubuntu-22.04" - if: ${{ always() }} - needs: - - get-all-libraries - - test-all-metadata - permissions: write-all - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: "☁️ Checkout repository" - uses: actions/checkout@v4 - - name: "πŸ”§ Setup java" - uses: actions/setup-java@v4 - with: - distribution: 'oracle' - java-version: '21' - - name: "✏️ PR for supported versions" - run: | - git config --local user.email "actions@github.com" - git config --local user.name "Github Actions" - git fetch origin check-new-library-versions/$(date '+%Y-%m-%d') - git checkout check-new-library-versions/$(date '+%Y-%m-%d') - gh pr create --title "Update supported library versions" --body "This pull request updates supported versions of the existing libraries in the repo" - - name: "Download artifacts for unsupported versions" - uses: actions/download-artifact@v4 - with: - path: ./unsupported - - name: "✏️ Issue for unsupported versions" - run: | - git config --local user.email "actions@github.com" - git config --local user.name "Github Actions" - - LABEL="library-update" - ALL_LIBRARIES=$(ls unsupported) - FORMATTED_BODY=$(./gradlew -q groupLibrariesByName --libraries="$ALL_LIBRARIES") - - EXISTING_ISSUE=$(gh issue list --label "$LABEL" --state open --limit 1 --json url | jq -r '.[0].url') - if [ $EXISTING_ISSUE != "null" ]; then - gh issue edit $EXISTING_ISSUE --body "$FORMATTED_BODY" - else - gh issue create --title "List unsupported libraries versions" --body "$FORMATTED_BODY" --label $LABEL - fi diff --git a/.github/workflows/disable-docker.sh b/.github/workflows/disable-docker.sh new file mode 100644 index 000000000..4387fabf1 --- /dev/null +++ b/.github/workflows/disable-docker.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Copyright and related rights waived via CC0 +# +# You should have received a copy of the CC0 legalcode along with this +# work. If not, see . + +# Purpose: +# Make Docker unable to access the network during tests by: +# 1) Enabling the discard service on localhost:9 (TCP/UDP) via inetd to accept and immediately discard traffic. +# 2) Pointing Docker's HTTP(S) proxy environment variables to http(s)://localhost:9 using a systemd drop-in. +# +# Why: +# - Tests may only use pre-pulled/allowed Docker images. This prevents Docker from downloading anything else. +# - Using the discard service avoids long TCP connection timeouts: the local port accepts connections and discards +# data quickly, causing Docker's proxy connections to fail fast. +# +# Notes: +# - This script is designed for GitHub Actions Ubuntu runners with sudo. +# - It is idempotent: re-running it won't duplicate config lines or unnecessarily restart Docker. + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +sudo apt-get install openbsd-inetd +sudo bash -c "cat ${SCRIPT_DIR}/discard-port.conf >> /etc/inetd.conf" +sudo systemctl start inetd +sudo mkdir /etc/systemd/system/docker.service.d +sudo bash -c "cat ${SCRIPT_DIR}/dockerd.service > /etc/systemd/system/docker.service.d/http-proxy.conf" +sudo systemctl daemon-reload +sudo systemctl restart docker +echo "Docker outbound network effectively disabled via proxy=http(s)://localhost:9 backed by inetd discard service." diff --git a/.github/workflows/run-consecutive-tests.sh b/.github/workflows/run-consecutive-tests.sh new file mode 100644 index 000000000..beaac23a7 --- /dev/null +++ b/.github/workflows/run-consecutive-tests.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# Copyright and related rights waived via CC0 +# +# You should have received a copy of the CC0 legalcode along with this +# work. If not, see . + +set -u + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Input parameters +TEST_COORDINATES="$1" +VERSIONS_JSON="$2" + +# Remove surrounding single quotes if present (when called from workflow) +VERSIONS_JSON="${VERSIONS_JSON#"${VERSIONS_JSON%%[!\']*}"}" +VERSIONS_JSON="${VERSIONS_JSON%"${VERSIONS_JSON##*[!\']}"}" + +# Parse versions with jq +readarray -t VERSIONS < <(echo "$VERSIONS_JSON" | jq -r '.[]') +export DELIMITER="========================================================================================" + +run_multiple_attempts() { + local stage="$1" + local max_attempts="$2" + local gradle_command="$3" + + echo "$DELIMITER" + echo " $TEST_COORDINATES:$VERSION stage $stage" + echo "$DELIMITER" + + local attempt=0 + local result=0 + + while [ $attempt -lt "$max_attempts" ]; do + local cmd_str="GVM_TCK_LV=\"$VERSION\" ./gradlew clean $gradle_command -Pcoordinates=\"$TEST_COORDINATES\"" + if [ $attempt -gt 0 ]; then + echo "Re-running stage '$stage' (attempt $((attempt + 1))/$max_attempts)" + fi + + eval "$cmd_str" + result=$? + + if [ "$result" -eq 0 ]; then + return 0 + fi + + attempt=$((attempt + 1)) + done + + echo "FAILED [$stage][$VERSION][$cmd_str]" + return $result +} + +for VERSION in "${VERSIONS[@]}"; do + echo "$DELIMITER" + echo " Testing $TEST_COORDINATES:$VERSION" + echo "$DELIMITER" + + + if ! run_multiple_attempts "javac compile" 1 javac; then + break + fi + + if ! run_multiple_attempts "native-image build" 1 nativeTestCompile; then + break + fi + + if ! run_multiple_attempts "native-image run" 3 test; then + break + fi + + echo "PASSED:$VERSION" +done + +exit 0 diff --git a/.github/workflows/test-all-metadata.yml b/.github/workflows/test-all-metadata.yml index 5b8dae16c..9c4490e11 100644 --- a/.github/workflows/test-all-metadata.yml +++ b/.github/workflows/test-all-metadata.yml @@ -63,15 +63,8 @@ jobs: - name: "Pull allowed docker images" run: | ./gradlew pullAllowedDockerImages --coordinates=${{ matrix.coordinates }} - - name: "Disable docker" - run: | - sudo apt-get install openbsd-inetd - sudo bash -c "cat ./.github/workflows/discard-port.conf >> /etc/inetd.conf" - sudo systemctl start inetd - sudo mkdir /etc/systemd/system/docker.service.d - sudo bash -c "cat ./.github/workflows/dockerd.service > /etc/systemd/system/docker.service.d/http-proxy.conf" - sudo systemctl daemon-reload - sudo systemctl restart docker + - name: "Disable docker networking" + run: bash ./.github/workflows/disable-docker.sh - name: "πŸ§ͺ Run '${{ matrix.coordinates }}' tests" run: | ./gradlew test -Pcoordinates=${{ matrix.coordinates }} diff --git a/.github/workflows/test-changed-metadata.yml b/.github/workflows/test-changed-metadata.yml index df7e33a2c..d29dceebb 100644 --- a/.github/workflows/test-changed-metadata.yml +++ b/.github/workflows/test-changed-metadata.yml @@ -66,15 +66,8 @@ jobs: - name: "Pull allowed docker images" run: | ./gradlew pullAllowedDockerImages --coordinates=${{ matrix.coordinates }} - - name: "Disable docker" - run: | - sudo apt-get install openbsd-inetd - sudo bash -c "cat ./.github/workflows/discard-port.conf >> /etc/inetd.conf" - sudo systemctl start inetd - sudo mkdir /etc/systemd/system/docker.service.d - sudo bash -c "cat ./.github/workflows/dockerd.service > /etc/systemd/system/docker.service.d/http-proxy.conf" - sudo systemctl daemon-reload - sudo systemctl restart docker + - name: "Disable docker networking" + run: bash ./.github/workflows/disable-docker.sh - name: "πŸ”Ž Check metadata config files content" run: | ./gradlew checkConfigFiles --coordinates=${{ matrix.coordinates }} diff --git a/.github/workflows/tryPushVersionsUpdate.sh b/.github/workflows/tryPushVersionsUpdate.sh deleted file mode 100644 index 4d807c3bd..000000000 --- a/.github/workflows/tryPushVersionsUpdate.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -:' This script tries to run addTestedVersion gradle task which adds new version in the tested-versions list of the proper index.json file. -Since the script could be executed from multiple parallel jobs, we want to avoid two things here: overwriting of previous changes and merge conflicts. -To prevent overwriting of changes that some job already created, we only push changes from the current job if we are 0 commits behind the origin branch. -Once that is achieved, we can try to push changes. -If the push was rejected because of a merge conflict, we are: removing changes of the current job, rebasing, and doing the process again until it succeeds. -' - -set -x - -git config --local user.email "actions@github.com" -git config --local user.name "Github Actions" - -BRANCH="check-new-library-versions/$(date '+%Y-%m-%d')" -git fetch origin "$BRANCH" -git checkout "$BRANCH" - -while [ true ] -do - # update the list of tested versions - ./gradlew addTestedVersion --coordinates="$1" --lastSupportedVersion="$2" - - # commit changes - git add -u - git commit -m "$1" - - # only push changes if we are not behind the remote branch - if [ "$(git rev-list --count origin/$BRANCH --not $BRANCH)" -eq 0 ] - then - # try to push changes - git push origin "$BRANCH" - PUSH_RETVAL=$? - if [ "$PUSH_RETVAL" -eq 0 ] - then - # if the push was successful, we can exit the loop - break - fi - fi - - # we are either behind the remote branch or we have a merge conflict => remove changes and rebase accepting incoming changes - git reset --hard HEAD~1 - git fetch origin "$BRANCH" - git rebase -X theirs "origin/$BRANCH" -done - - diff --git a/.github/workflows/verify-new-library-version-compatibility.yml b/.github/workflows/verify-new-library-version-compatibility.yml new file mode 100644 index 000000000..46e6e90e5 --- /dev/null +++ b/.github/workflows/verify-new-library-version-compatibility.yml @@ -0,0 +1,266 @@ +name: "Verify compatibility with latest library versions" + +on: + schedule: + - cron: '0 0 * * 0' + workflow_dispatch: + +permissions: + contents: write + actions: write + +concurrency: + group: "workflow=${{ github.workflow }},ref=${{ github.event.ref }},pr=${{ github.event.pull_request.id }}" + cancel-in-progress: true + +jobs: + get-all-libraries: + name: "πŸ“‹ Get list of all supported libraries with newer versions" + if: github.repository == 'oracle/graalvm-reachability-metadata' + runs-on: ubuntu-22.04 + timeout-minutes: 5 + permissions: write-all + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + branch: ${{ steps.set-branch-name.outputs.branch }} + steps: + - name: "☁️ Checkout repository" + uses: actions/checkout@v4 + + - name: "πŸ”§ Prepare environment" + uses: graalvm/setup-graalvm@v1 + with: + java-version: '21' + distribution: 'graalvm' + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: "πŸ“… Set branch name" + id: set-branch-name + run: | + BRANCH_NAME="check-new-library-versions/$(date '+%Y-%m-%dT%H-%M')" + echo "branch=$BRANCH_NAME" >> $GITHUB_OUTPUT + + - name: "πŸ•ΈοΈ Populate matrix" + id: set-matrix + run: | + echo "matrix=$(./gradlew fetchExistingLibrariesWithNewerVersions --quiet | sed -n '/\[/,$p')" >> $GITHUB_OUTPUT + + - name: "πŸ”¨ Create branch" + run: | + git config --local user.email "actions@github.com" + git config --local user.name "Github Actions" + git checkout -b "${{ steps.set-branch-name.outputs.branch }}" + git push origin "${{ steps.set-branch-name.outputs.branch }}" + + test-all-metadata: + name: "πŸ§ͺ ${{ matrix.item.name }}" + runs-on: ubuntu-22.04 + needs: get-all-libraries + permissions: write-all + env: + CURRENT_JOB_NAME: "πŸ§ͺ ${{ matrix.item.name }}" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUE_TITLE_PREFIX: "[Automation] " + ISSUE_TITLE_MIDDLE: " fails for " + LOG_LINES: "300" + strategy: + fail-fast: false + matrix: + item: ${{ fromJson(needs.get-all-libraries.outputs.matrix) }} + steps: + - name: "☁️ Checkout repository" + uses: actions/checkout@v4 + + - name: "πŸ”§ Setup java" + uses: actions/setup-java@v4 + with: + distribution: 'oracle' + java-version: '21' + + - name: "πŸ”§ Prepare environment" + uses: graalvm/setup-graalvm@v1 + with: + set-java-home: 'false' + java-version: 21 + distribution: 'graalvm' + github-token: ${{ secrets.GITHUB_TOKEN }} + native-image-job-reports: 'true' + + - name: "Check for an existing issue and skip further testing if found" + id: check_existing_issue + run: | + GROUP_ID="$(echo "${{ matrix.item.name }}" | cut -d: -f1)" + ARTIFACT_ID="$(echo "${{ matrix.item.name }}" | cut -d: -f2)" + + readarray -t VERSIONS < <(echo '${{ toJson(matrix.item.versions) }}' | jq -r '.[]') + FIRST_TESTING_VERSION="${VERSIONS[0]}" + + TITLE_SEARCH="${{ env.ISSUE_TITLE_MIDDLE }}$GROUP_ID:$ARTIFACT_ID:$FIRST_TESTING_VERSION" + + ISSUE_NUMBER=$(gh issue list --repo "${{ github.repository }}" --state open --search "in:title $TITLE_SEARCH" --json number,title --jq \ + '.[] | select(.title | endswith("'"$TITLE_SEARCH"'")) | .number') + + if [[ -n "$ISSUE_NUMBER" ]]; then + echo "skip=true" >> "$GITHUB_OUTPUT" + echo "There is no progress since last time this version was tested. Skipping further steps." + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: "Extract test path and library version" + if: steps.check_existing_issue.outputs.skip != 'true' + id: extract-params + run: | + LIBRARY_PATH=$(echo "${{ matrix.item.name }}" | sed 's/:/\//g') + LATEST_VERSION=$(find tests/src/$LIBRARY_PATH/* -maxdepth 1 -type d | sort -V | tail -1 | cut -d '/' -f5) + TEST_PATH="$LIBRARY_PATH/$LATEST_VERSION" + TEST_COORDINATES=$(echo "$TEST_PATH" | tr / :) + + echo "LATEST_VERSION=$LATEST_VERSION" >> ${GITHUB_ENV} + echo "TEST_PATH=$TEST_PATH" >> ${GITHUB_ENV} + echo "TEST_COORDINATES=$TEST_COORDINATES" >> ${GITHUB_ENV} + + - name: "Pull allowed docker images" + if: steps.check_existing_issue.outputs.skip != 'true' + run: ./gradlew pullAllowedDockerImages --coordinates="${{ env.TEST_COORDINATES }}" + + - name: "Disable docker networking" + if: steps.check_existing_issue.outputs.skip != 'true' + run: bash ./.github/workflows/disable-docker.sh + + - name: "πŸ§ͺ Run '${{ env.TEST_COORDINATES }}' tests" + if: steps.check_existing_issue.outputs.skip != 'true' + id: runtests + run: | + bash ./.github/workflows/run-consecutive-tests.sh "${{ env.TEST_COORDINATES }}" '${{ toJson(matrix.item.versions) }}' 2>&1 | tee test_results.txt || true + + # Extract successful versions + grep "^PASSED:" test_results.txt | sed 's/PASSED://g' > successful_versions.txt + echo "successful_versions<> $GITHUB_OUTPUT + cat successful_versions.txt >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + # Extract failure type and failed version + awk -F'[][]' '/^FAILED/ {print "failure_type="$2; print "failed_version="$4; print "failed_command="$6}' test_results.txt >> $GITHUB_OUTPUT + + # Fetch the job URL + JOB_ID=$( + gh run view "${{ github.run_id }}" --repo "${{ github.repository }}" --json jobs \ + | jq -r --arg name "$CURRENT_JOB_NAME" '.jobs[] | select(.name | startswith($name)) | .databaseId' \ + | head -n1 + ) + if [ -z "$JOB_ID" ] || [ "$JOB_ID" = "null" ]; then + # Fallback to run-level URL if job lookup fails + echo "runner_log_url=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_OUTPUT + else + echo "runner_log_url=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/$JOB_ID" >> $GITHUB_OUTPUT + fi + + # Extract log tail + echo "log_tail<> $GITHUB_OUTPUT + tail "-n${{ env.LOG_LINES }}" test_results.txt | head -c 900000 >> $GITHUB_OUTPUT + echo "" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: "βœ”οΈ New library versions are supported (with locks, waiting and retries)" + if: steps.check_existing_issue.outputs.skip != 'true' && steps.runtests.outputs.successful_versions != '' + env: + BRANCH: ${{ needs.get-all-libraries.outputs.branch }} + run: | + set -euo pipefail + git config --local user.email "actions@github.com" + git config --local user.name "Github Actions" + + update_new_versions() { + while read version; do + if [ -n "$version" ]; then + ./gradlew addTestedVersion --coordinates="${{ matrix.item.name }}:$version" --lastSupportedVersion="${{ env.LATEST_VERSION }}" + fi + done < successful_versions.txt + } + + # Small jitter to reduce contention start + sleep $((RANDOM % 5 + 1)) + + for i in {1..10}; do + # Always start from the latest remote state + git fetch origin "$BRANCH" + git checkout -B "$BRANCH" "origin/$BRANCH" + + update_new_versions + + # If nothing changed, exit early + if git status --porcelain | grep -q .; then + git add -u + git commit -m "Update tested versions for ${{ matrix.item.name }}" + else + echo "No changes to commit for ${{ matrix.item.name }}." + exit 0 + fi + + if git push origin "$BRANCH"; then + echo "Pushed successfully." + exit 0 + fi + + echo "Push failed (likely concurrent update). Waiting and retrying..." + sleep 5 + done + + echo "Timed out waiting to push updates after concurrent jobs." + exit 1 + + - name: "❗ New library version is not supported" + if: steps.check_existing_issue.outputs.skip != 'true' && steps.runtests.outputs.failed_version != '' + run: | + git config --local user.email "actions@github.com" + git config --local user.name "Github Actions" + + FAILED_VERSION="${{ steps.runtests.outputs.failed_version }}" + REPO="${{ github.repository }}" + TITLE="${{ env.ISSUE_TITLE_PREFIX }}${{ steps.runtests.outputs.failure_type }}${{ env.ISSUE_TITLE_MIDDLE }}${{ matrix.item.name }}:$FAILED_VERSION" + + BODY_FILE=$(mktemp) + # Use single-quoted here-doc to disable any shell expansion of log content + cat > "$BODY_FILE" <<'EOF' + Failure kind: ${{ steps.runtests.outputs.failure_type }} + Reproducer: `${{ steps.runtests.outputs.failed_command }}` + Runner log: ${{ steps.runtests.outputs.runner_log_url }} + Last ${{ env.LOG_LINES }} lines of the log: + ```console + ${{ steps.runtests.outputs.log_tail }} + ``` + EOF + + ISSUE_NUMBER=$(gh issue list --repo "$REPO" --state open --search "$TITLE" --json number,title --jq '.[] | select(.title | startswith("'"$TITLE"'")) | .number') + if [ -n "$ISSUE_NUMBER" ]; then + echo "Updating existing issue #$ISSUE_NUMBER" + gh issue edit "$ISSUE_NUMBER" --repo "$REPO" --body-file "$BODY_FILE" + else + echo "Creating new issue" + gh issue create --repo "$REPO" --title "$TITLE" --body-file "$BODY_FILE" + fi + + rm "$BODY_FILE" + + process-results: + name: "πŸ§ͺ Process results" + runs-on: ubuntu-22.04 + permissions: write-all + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: ${{ always() }} + needs: + - get-all-libraries + - test-all-metadata + steps: + - name: "☁️ Checkout repository" + uses: actions/checkout@v4 + + - name: "✏️ PR for supported versions" + run: | + git config --local user.email "actions@github.com" + git config --local user.name "Github Actions" + git fetch origin ${{ needs.get-all-libraries.outputs.branch }} + git checkout ${{ needs.get-all-libraries.outputs.branch }} + gh pr create --title "[Automation] Update supported library versions $(date '+%Y-%m-%dT%H:%M')" --body "This pull request updates supported versions of the existing libraries in the repo" diff --git a/tests/tck-build-logic/src/main/groovy/org.graalvm.internal.tck-harness.gradle b/tests/tck-build-logic/src/main/groovy/org.graalvm.internal.tck-harness.gradle index 14ab8cd4a..6875361b0 100644 --- a/tests/tck-build-logic/src/main/groovy/org.graalvm.internal.tck-harness.gradle +++ b/tests/tck-build-logic/src/main/groovy/org.graalvm.internal.tck-harness.gradle @@ -19,6 +19,9 @@ import org.graalvm.internal.tck.TestedVersionUpdaterTask import org.graalvm.internal.tck.harness.tasks.TestInvocationTask import org.graalvm.internal.tck.harness.tasks.CheckstyleInvocationTask import org.graalvm.internal.tck.harness.tasks.CleanInvocationTask +import org.graalvm.internal.tck.harness.tasks.JavacInvocationTask +import org.graalvm.internal.tck.harness.tasks.JavaTestInvocationTask +import org.graalvm.internal.tck.harness.tasks.NativeTestCompileInvocationTask import org.graalvm.internal.tck.updaters.FetchExistingLibrariesWithNewerVersionsTask import org.graalvm.internal.tck.updaters.GroupUnsupportedLibraries @@ -43,6 +46,24 @@ Provider checkstyle = tasks.register("checkstyle") { task -> task.setGroup(JavaBasePlugin.VERIFICATION_GROUP) } + // gradle javac -Pcoordinates= +Provider javac = tasks.register("javac") { task -> + task.setDescription("Compiles sources (javac) for all subprojects") + task.setGroup(LifecycleBasePlugin.BUILD_GROUP) +} + + // gradle nativeTestCompile -Pcoordinates= +Provider nativeTestCompile = tasks.register("nativeTestCompile") { task -> + task.setDescription("Compiles native tests (nativeTestCompile) for all subprojects") + task.setGroup(LifecycleBasePlugin.BUILD_GROUP) +} + + // gradle javaTest -Pcoordinates= +Provider javaTest = tasks.register("javaTest") { task -> + task.setDescription("Runs JVM tests (Gradle 'test') for all subprojects") + task.setGroup(JavaBasePlugin.VERIFICATION_GROUP) +} + tasks.named("check").configure { dependsOn(checkstyle) } @@ -72,6 +93,30 @@ for (String coordinates in matchingCoordinates) { clean.configure { dependsOn(cleanTaskName) } + + String javacTaskName = generateTaskName("javac", coordinates) + if ((!tasks.getNames().contains(javacTaskName))) { + tasks.register(javacTaskName, JavacInvocationTask, coordinates) + } + javac.configure { + dependsOn(javacTaskName) + } + + String nativeTestCompileTaskName = generateTaskName("nativeTestCompile", coordinates) + if ((!tasks.getNames().contains(nativeTestCompileTaskName))) { + tasks.register(nativeTestCompileTaskName, NativeTestCompileInvocationTask, coordinates) + } + nativeTestCompile.configure { + dependsOn(nativeTestCompileTaskName) + } + + String javaTestTaskName = generateTaskName("javaTest", coordinates) + if ((!tasks.getNames().contains(javaTestTaskName))) { + tasks.register(javaTestTaskName, JavaTestInvocationTask, coordinates) + } + javaTest.configure { + dependsOn(javaTestTaskName) + } } // gradle diff -PbaseCommit= -PnewCommit= diff --git a/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/JavaTestInvocationTask.groovy b/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/JavaTestInvocationTask.groovy new file mode 100644 index 000000000..efcf472f5 --- /dev/null +++ b/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/JavaTestInvocationTask.groovy @@ -0,0 +1,35 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ + +package org.graalvm.internal.tck.harness.tasks + +import org.gradle.api.tasks.Input + +import javax.inject.Inject +/** + * Task that is used to run JVM tests (Gradle 'test') on subprojects. + */ +@SuppressWarnings("unused") +abstract class JavaTestInvocationTask extends AbstractSubprojectTask { + + @Inject + JavaTestInvocationTask(String coordinates) { + super(coordinates) + } + + @Override + @Input + List getCommand() { + return [tckExtension.repoRoot.get().asFile.toPath().resolve("gradlew").toString(), "test"] + } + + @Override + protected String getErrorMessage(int exitCode) { + "Java tests failed" + } + +} diff --git a/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/JavacInvocationTask.groovy b/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/JavacInvocationTask.groovy new file mode 100644 index 000000000..63434e2eb --- /dev/null +++ b/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/JavacInvocationTask.groovy @@ -0,0 +1,35 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ + +package org.graalvm.internal.tck.harness.tasks + +import org.gradle.api.tasks.Input + +import javax.inject.Inject +/** + * Task that is used to compile subprojects with javac. + */ +@SuppressWarnings("unused") +abstract class JavacInvocationTask extends AbstractSubprojectTask { + + @Inject + JavacInvocationTask(String coordinates) { + super(coordinates) + } + + @Override + @Input + List getCommand() { + return [tckExtension.repoRoot.get().asFile.toPath().resolve("gradlew").toString(), "compileTestJava"] + } + + @Override + protected String getErrorMessage(int exitCode) { + "Compilation failed" + } + +} diff --git a/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/NativeTestCompileInvocationTask.groovy b/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/NativeTestCompileInvocationTask.groovy new file mode 100644 index 000000000..158b2dfbd --- /dev/null +++ b/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/harness/tasks/NativeTestCompileInvocationTask.groovy @@ -0,0 +1,35 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ + +package org.graalvm.internal.tck.harness.tasks + +import org.gradle.api.tasks.Input + +import javax.inject.Inject +/** + * Task that is used to compile native tests (Gradle 'nativeTestCompile') on subprojects. + */ +@SuppressWarnings("unused") +abstract class NativeTestCompileInvocationTask extends AbstractSubprojectTask { + + @Inject + NativeTestCompileInvocationTask(String coordinates) { + super(coordinates) + } + + @Override + @Input + List getCommand() { + return [tckExtension.repoRoot.get().asFile.toPath().resolve("gradlew").toString(), "nativeTestCompile"] + } + + @Override + protected String getErrorMessage(int exitCode) { + "Native test compilation failed" + } + +} diff --git a/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/updaters/FetchExistingLibrariesWithNewerVersionsTask.groovy b/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/updaters/FetchExistingLibrariesWithNewerVersionsTask.groovy index 23197c1b7..c230a5693 100644 --- a/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/updaters/FetchExistingLibrariesWithNewerVersionsTask.groovy +++ b/tests/tck-build-logic/src/main/groovy/org/graalvm/internal/tck/updaters/FetchExistingLibrariesWithNewerVersionsTask.groovy @@ -24,10 +24,6 @@ abstract class FetchExistingLibrariesWithNewerVersionsTask extends DefaultTask { @Input abstract ListProperty getAllLibraryCoordinates() - @Input - @Option(option = "matrixLimit", description = "Sets the maximum number of coordinates in the final matrix") - abstract Property getMatrixLimit() - private static final List INFRASTRUCTURE_TESTS = List.of("samples", "org.example") @TaskAction @@ -50,17 +46,15 @@ abstract class FetchExistingLibrariesWithNewerVersionsTask extends DefaultTask { } } - if (newerVersions.size() > getMatrixLimit().get()) { - newerVersions = newerVersions.subList(0, getMatrixLimit().get()) + def map = [:] + newerVersions.each { coord -> + def (group, artifact, version) = coord.tokenize(':') + def key = "${group}:${artifact}" + map[key] = (map[key] ?: []) + version } + def pairs = map.collect { k, v -> [name: k, versions: v] } - def matrix = [ - "coordinates": newerVersions, - "version" : ["17"], - "os" : ["ubuntu-latest"] - ] - - new File(System.getenv("GITHUB_OUTPUT")).append("matrix::${JsonOutput.toJson(matrix)}") + println JsonOutput.toJson(pairs) } static List getNewerVersionsFor(String library, String startingVersion) { @@ -88,14 +82,10 @@ abstract class FetchExistingLibrariesWithNewerVersionsTask extends DefaultTask { int indexOfStartingVersion = allVersions.indexOf(startingVersion); if (indexOfStartingVersion < 0) { - System.out.println("Cannot find starting version in index file: " + libraryName + " for version " + startingVersion); return new ArrayList<>(); } allVersions = allVersions.subList(indexOfStartingVersion, allVersions.size()); - if (allVersions.size() <= 1) { - System.out.println("Cannot find newer versions for " + libraryName + " after the version " + startingVersion); - } return allVersions.subList(1, allVersions.size()); } diff --git a/tests/tck-build-logic/src/main/java/org/graalvm/internal/tck/TestedVersionUpdaterTask.java b/tests/tck-build-logic/src/main/java/org/graalvm/internal/tck/TestedVersionUpdaterTask.java index 87163c3bf..1ec9a7346 100644 --- a/tests/tck-build-logic/src/main/java/org/graalvm/internal/tck/TestedVersionUpdaterTask.java +++ b/tests/tck-build-logic/src/main/java/org/graalvm/internal/tck/TestedVersionUpdaterTask.java @@ -19,6 +19,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.util.Comparator; import java.util.List; @@ -65,6 +66,11 @@ void run() throws IllegalStateException, IOException { DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter(); prettyPrinter.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE); - objectMapper.writer(prettyPrinter).writeValue(coordinatesMetadataIndex, entries); + // Ensure the JSON file ends with a trailing EOL + String json = objectMapper.writer(prettyPrinter).writeValueAsString(entries); + if (!json.endsWith("\n")) { + json = json + System.lineSeparator(); + } + Files.writeString(coordinatesMetadataIndex.toPath(), json, java.nio.charset.StandardCharsets.UTF_8); } }