From 823205fbb7a00fcd611abe6bab5ebe3357ca868c Mon Sep 17 00:00:00 2001 From: Jagdish Prajapati Date: Sat, 9 May 2026 02:56:38 +0530 Subject: [PATCH 1/6] Add lint-changed task in Java workflow --- .github/workflows/java.yml | 21 +++++++++++++-- bin/lint-changed-exercise | 54 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 bin/lint-changed-exercise diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml index ef2f2017e..e5b689abc 100644 --- a/.github/workflows/java.yml +++ b/.github/workflows/java.yml @@ -25,8 +25,9 @@ jobs: run: ./gradlew compileStarterTestJava --continue working-directory: exercises - lint: - name: Lint Java files using Checkstyle + lint-all: + name: Lint all Java files using Checkstyle + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd @@ -39,6 +40,22 @@ jobs: run: ./gradlew check --exclude-task test --continue working-directory: exercises + lint-changed: + name: Lint changed Java exercises using Checkstyle + if: github.event_name == 'pull_request' + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + fetch-depth: 0 + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 + with: + java-version: 21 + distribution: "temurin" + - name: Lint changed exercises + run: bin/lint-changed-exercise + test-all: name: Test all exercises using java-test-runner if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' diff --git a/bin/lint-changed-exercise b/bin/lint-changed-exercise new file mode 100644 index 000000000..7fc6b96dc --- /dev/null +++ b/bin/lint-changed-exercise @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +set -eo pipefail + +# Determine the base branch of the PR +BASE_BRANCH=${GITHUB_BASE_REF:-main} + +# Fetch full history for proper diff +git fetch origin "$BASE_BRANCH" + +# Compute merge base +MERGE_BASE=$(git merge-base HEAD origin/"$BASE_BRANCH") + +# Get changed files relative to merge base +changed_files=$(git diff --name-only "$MERGE_BASE" HEAD) + +# If any Gradle build file changed, run the full suite and exit +if echo "$changed_files" | grep -qE '\.(gradle|gradlew|bat)$|settings\.gradle'; then + echo "Gradle build files changed, running full lint suite..." + cd exercises && ./gradlew check --exclude-task test --continue + exit 0 +fi + +# Extract unique exercise directories +changed_exercises=$(echo "$changed_files" | \ + grep -E '^exercises/(practice|concept)/[^/]+/.+\.java$' | \ + cut -d/ -f1-3 | sort -u) + +if [ -z "$changed_exercises" ]; then + echo "No relevant exercises changed, skipping linting." + exit 0 +fi + +# Print exercises +echo "Changed exercises detected:" +echo "$changed_exercises" +echo "----------------------------------------" + +# Run lint checks +exit_code=0 +for dir in $changed_exercises; do + slug=$(basename "$dir") + + echo "========================================" + echo "=== Running checkstyle for $slug ===" + echo "========================================" + + if [[ $dir == exercises/practice/* ]]; then + ./exercises/gradlew -p exercises ":practice:$slug:check" --exclude-task test || exit_code=1 + elif [[ $dir == exercises/concept/* ]]; then + ./exercises/gradlew -p exercises ":concept:$slug:check" --exclude-task test || exit_code=1 + fi +done + +exit $exit_code From e7630145b006bf07a8d16db51dc4e68895b60e67 Mon Sep 17 00:00:00 2001 From: Jagdish Prajapati Date: Sat, 9 May 2026 03:36:19 +0530 Subject: [PATCH 2/6] ci: implement build-changed strategy for targeted test compilation --- .github/workflows/java.yml | 19 +++++++++++++- bin/build-changed-exercise | 54 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100755 bin/build-changed-exercise diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml index ef2f2017e..eb9393519 100644 --- a/.github/workflows/java.yml +++ b/.github/workflows/java.yml @@ -11,8 +11,9 @@ on: workflow_dispatch: jobs: - build: + build-all: name: Check if tests compile cleanly with starter sources + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd @@ -25,6 +26,22 @@ jobs: run: ./gradlew compileStarterTestJava --continue working-directory: exercises + build-changed: + name: Check if changed exercise tests compile cleanly with starter sources + if: github.event_name == 'pull_request' + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + fetch-depth: 0 + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 + with: + java-version: 21 + distribution: "temurin" + - name: Check if changed exercise tests compile cleanly + run: bin/build-changed-exercise + lint: name: Lint Java files using Checkstyle runs-on: ubuntu-24.04 diff --git a/bin/build-changed-exercise b/bin/build-changed-exercise new file mode 100755 index 000000000..ebb52a69e --- /dev/null +++ b/bin/build-changed-exercise @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +set -eo pipefail + +# Determine the base branch of the PR +BASE_BRANCH=${GITHUB_BASE_REF:-main} + +# Fetch full history for proper diff +git fetch origin "$BASE_BRANCH" + +# Compute merge base +MERGE_BASE=$(git merge-base HEAD origin/"$BASE_BRANCH") + +# Get changed files relative to merge base +changed_files=$(git diff --name-only "$MERGE_BASE" HEAD) + +# If any Gradle build file changed, run the full suite and exit +if echo "$changed_files" | grep -qE '\.(gradle|gradlew|bat)$|settings\.gradle'; then + echo "Gradle build files changed, running full build suite..." + cd exercises && ./gradlew compileStarterTestJava --continue + exit 0 +fi + +# Extract unique exercise directories +changed_exercises=$(echo "$changed_files" | \ + grep -E '^exercises/(practice|concept)/[^/]+/.+\.java$' | \ + cut -d/ -f1-3 | sort -u || true) + +if [ -z "$changed_exercises" ]; then + echo "No relevant exercises changed, skipping compile checks." + exit 0 +fi + +# Print exercises +echo "Changed exercises detected:" +echo "$changed_exercises" +echo "----------------------------------------" + +# Run build compile checks +exit_code=0 +for dir in $changed_exercises; do + slug=$(basename "$dir") + + echo "========================================" + echo "=== Running compileStarterTestJava for $slug ===" + echo "========================================" + + if [[ $dir == exercises/practice/* ]]; then + ./exercises/gradlew -p exercises ":practice:$slug:compileStarterTestJava" || exit_code=1 + elif [[ $dir == exercises/concept/* ]]; then + ./exercises/gradlew -p exercises ":concept:$slug:compileStarterTestJava" || exit_code=1 + fi +done + +exit $exit_code From 116ea887e26ca4ba1a02a0fc3ee030f5f68312ba Mon Sep 17 00:00:00 2001 From: Jagdish Prajapati Date: Sat, 9 May 2026 22:53:32 +0530 Subject: [PATCH 3/6] Combine common logic --- bin/build-changed-exercise | 25 ++++--------------------- bin/common.sh | 36 ++++++++++++++++++++++++++++++++++++ bin/lint-changed-exercise | 25 ++++--------------------- bin/test-changed-exercise | 25 ++++--------------------- 4 files changed, 48 insertions(+), 63 deletions(-) create mode 100644 bin/common.sh diff --git a/bin/build-changed-exercise b/bin/build-changed-exercise index ebb52a69e..9238b6744 100755 --- a/bin/build-changed-exercise +++ b/bin/build-changed-exercise @@ -1,29 +1,12 @@ #!/usr/bin/env bash set -eo pipefail -# Determine the base branch of the PR -BASE_BRANCH=${GITHUB_BASE_REF:-main} - -# Fetch full history for proper diff -git fetch origin "$BASE_BRANCH" - -# Compute merge base -MERGE_BASE=$(git merge-base HEAD origin/"$BASE_BRANCH") - -# Get changed files relative to merge base -changed_files=$(git diff --name-only "$MERGE_BASE" HEAD) +source "$(dirname "$0")/common.sh" # If any Gradle build file changed, run the full suite and exit -if echo "$changed_files" | grep -qE '\.(gradle|gradlew|bat)$|settings\.gradle'; then - echo "Gradle build files changed, running full build suite..." - cd exercises && ./gradlew compileStarterTestJava --continue - exit 0 -fi - -# Extract unique exercise directories -changed_exercises=$(echo "$changed_files" | \ - grep -E '^exercises/(practice|concept)/[^/]+/.+\.java$' | \ - cut -d/ -f1-3 | sort -u || true) +check_gradle_changes \ + "cd exercises && ./gradlew compileStarterTestJava --continue" \ + "Gradle build files changed, running full build suite..." if [ -z "$changed_exercises" ]; then echo "No relevant exercises changed, skipping compile checks." diff --git a/bin/common.sh b/bin/common.sh new file mode 100644 index 000000000..005d275e0 --- /dev/null +++ b/bin/common.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -eo pipefail + +# Determine the base branch of the PR +BASE_BRANCH=${GITHUB_BASE_REF:-main} + +# Fetch full history for proper diff +git fetch origin "$BASE_BRANCH" + +# Compute merge base +MERGE_BASE=$(git merge-base HEAD origin/"$BASE_BRANCH") + +# Get changed files relative to merge base +changed_files=$(git diff --name-only "$MERGE_BASE" HEAD) + +# Function to check if Gradle build files changed and run a command +check_gradle_changes() { + local command="$1" + local message="$2" + + if echo "$changed_files" | grep -qE '\.(gradle|gradlew|bat)$|settings\.gradle'; then + echo "$message" + eval "$command" + exit 0 + fi +} + +# Extract unique exercise directories +get_changed_exercises() { + echo "$changed_files" | \ + grep -E '^exercises/(practice|concept)/[^/]+/.+\.java$' | \ + cut -d/ -f1-3 | sort -u || true +} + +# Variable for reuse +changed_exercises=$(get_changed_exercises) diff --git a/bin/lint-changed-exercise b/bin/lint-changed-exercise index 7fc6b96dc..bbb6efc26 100644 --- a/bin/lint-changed-exercise +++ b/bin/lint-changed-exercise @@ -1,29 +1,12 @@ #!/usr/bin/env bash set -eo pipefail -# Determine the base branch of the PR -BASE_BRANCH=${GITHUB_BASE_REF:-main} - -# Fetch full history for proper diff -git fetch origin "$BASE_BRANCH" - -# Compute merge base -MERGE_BASE=$(git merge-base HEAD origin/"$BASE_BRANCH") - -# Get changed files relative to merge base -changed_files=$(git diff --name-only "$MERGE_BASE" HEAD) +source "$(dirname "$0")/common.sh" # If any Gradle build file changed, run the full suite and exit -if echo "$changed_files" | grep -qE '\.(gradle|gradlew|bat)$|settings\.gradle'; then - echo "Gradle build files changed, running full lint suite..." - cd exercises && ./gradlew check --exclude-task test --continue - exit 0 -fi - -# Extract unique exercise directories -changed_exercises=$(echo "$changed_files" | \ - grep -E '^exercises/(practice|concept)/[^/]+/.+\.java$' | \ - cut -d/ -f1-3 | sort -u) +check_gradle_changes \ + "cd exercises && ./gradlew check --exclude-task test --continue" \ + "Gradle build files changed, running full lint suite..." if [ -z "$changed_exercises" ]; then echo "No relevant exercises changed, skipping linting." diff --git a/bin/test-changed-exercise b/bin/test-changed-exercise index b18a488e8..4e71b25a4 100755 --- a/bin/test-changed-exercise +++ b/bin/test-changed-exercise @@ -1,29 +1,12 @@ #!/usr/bin/env bash set -eo pipefail -# Determine the base branch of the PR -BASE_BRANCH=${GITHUB_BASE_REF:-main} - -# Fetch full history for proper diff -git fetch origin "$BASE_BRANCH" - -# Compute merge base -MERGE_BASE=$(git merge-base HEAD origin/"$BASE_BRANCH") - -# Get changed files relative to merge base -changed_files=$(git diff --name-only "$MERGE_BASE" HEAD) +source "$(dirname "$0")/common.sh" # If any Gradle build file changed, run the full suite and exit -if echo "$changed_files" | grep -qE '\.(gradle|gradlew|bat)$|settings\.gradle'; then - echo "Gradle build files changed, running full test suite..." - ./bin/test-with-test-runner - exit 0 -fi - -# Extract unique exercise directories -changed_exercises=$(echo "$changed_files" | \ - grep -E '^exercises/(practice|concept)/[^/]+/.+\.java$' | \ - cut -d/ -f1-3 | sort -u) +check_gradle_changes \ + "./bin/test-with-test-runner" \ + "Gradle build files changed, running full test suite..." if [ -z "$changed_exercises" ]; then echo "No relevant exercises changed, skipping tests." From cf51d14812ad9f3dd7346266bff600c662a51885 Mon Sep 17 00:00:00 2001 From: Jagdish Prajapati Date: Sat, 9 May 2026 22:57:43 +0530 Subject: [PATCH 4/6] Fix script permissions in Git index --- bin/common.sh | 0 bin/lint-changed-exercise | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/common.sh mode change 100644 => 100755 bin/lint-changed-exercise diff --git a/bin/common.sh b/bin/common.sh old mode 100644 new mode 100755 diff --git a/bin/lint-changed-exercise b/bin/lint-changed-exercise old mode 100644 new mode 100755 From 2b5b66a9b36fdb7c1ae8f3590f5cc7bf63c4a83a Mon Sep 17 00:00:00 2001 From: Jagdish Prajapati Date: Sat, 9 May 2026 23:20:40 +0530 Subject: [PATCH 5/6] Update Java version to 25 in CI --- .github/workflows/java.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml index ab88e39c8..2e43b527a 100644 --- a/.github/workflows/java.yml +++ b/.github/workflows/java.yml @@ -17,10 +17,10 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: - java-version: 21 + java-version: 25 distribution: "temurin" - name: Check if tests compile cleanly with starter sources run: ./gradlew compileStarterTestJava --continue @@ -34,10 +34,10 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: fetch-depth: 0 - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: - java-version: 21 + java-version: 25 distribution: "temurin" - name: Check if changed exercise tests compile cleanly run: bin/build-changed-exercise @@ -48,10 +48,10 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: - java-version: 21 + java-version: 25 distribution: "temurin" - name: Run checkstyle run: ./gradlew check --exclude-task test --continue @@ -65,10 +65,10 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: fetch-depth: 0 - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: - java-version: 21 + java-version: 25 distribution: "temurin" - name: Lint changed exercises run: bin/lint-changed-exercise From 8352d6f239420445a7146e10a8563c1d9b7e72ef Mon Sep 17 00:00:00 2001 From: Jagdish Prajapati Date: Sat, 9 May 2026 23:31:59 +0530 Subject: [PATCH 6/6] Add gradle wrapper files in detection --- bin/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/common.sh b/bin/common.sh index 005d275e0..9a84eb6d8 100755 --- a/bin/common.sh +++ b/bin/common.sh @@ -18,7 +18,7 @@ check_gradle_changes() { local command="$1" local message="$2" - if echo "$changed_files" | grep -qE '\.(gradle|gradlew|bat)$|settings\.gradle'; then + if echo "$changed_files" | grep -qE '(\.gradle|gradlew|\.bat|settings\.gradle|gradle-wrapper\.(properties|jar))$'; then echo "$message" eval "$command" exit 0