This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch revert-detect-dependencies-22022 in repository https://gitbox.apache.org/repos/asf/camel.git
commit 8380776aaa4e4b3cc840c206541f44c1961cc8a2 Author: Guillaume Nodet <[email protected]> AuthorDate: Thu Mar 26 11:37:44 2026 +0100 Revert "chore(ci): Fix parent POM dependency change detection (#22022)" This reverts the detect-dependencies CI action back to its original implementation. The reworked version is causing issues in CI. A proper fix will be done in #22247. Co-Authored-By: Claude Opus 4.6 <[email protected]> --- .github/actions/detect-dependencies/action.yaml | 64 +--- .github/actions/detect-dependencies/detect-test.sh | 393 +++------------------ .github/workflows/pr-build-main.yml | 5 +- 3 files changed, 52 insertions(+), 410 deletions(-) diff --git a/.github/actions/detect-dependencies/action.yaml b/.github/actions/detect-dependencies/action.yaml index e6334fc4d6b2..3db5cf5bcc70 100644 --- a/.github/actions/detect-dependencies/action.yaml +++ b/.github/actions/detect-dependencies/action.yaml @@ -21,17 +21,10 @@ inputs: github-token: description: 'The github token to access to the API' required: false - pr-id: - description: 'Id of the pull request' - required: true - github-repo: - description: 'The GitHub repository name (example, apache/camel)' + base-ref: + description: 'The base branch to compare against (defaults to github.base_ref)' required: false - default: 'apache/camel' - skip-mvnd-install: - description: 'Skip mvnd installation (use if already installed)' - required: false - default: 'false' + default: '' runs: using: "composite" steps: @@ -42,54 +35,5 @@ runs: - name: maven test env: GITHUB_TOKEN: ${{ inputs.github-token }} - MVND_DIR: ${{ steps.install-mvnd.outputs.mvnd-dir }} - PR_ID: ${{ inputs.pr-id }} - GITHUB_REPO: ${{ inputs.github-repo }} shell: bash - run: ${{ github.action_path }}/detect-test.sh "$MVND_DIR/mvnd" "$PR_ID" "$GITHUB_REPO" - - name: Post dependency change comment - if: always() - uses: actions/github-script@v8 - with: - github-token: ${{ inputs.github-token }} - script: | - const fs = require('fs'); - const commentFile = 'detect-dependencies-comment.md'; - if (!fs.existsSync(commentFile)) return; - const body = fs.readFileSync(commentFile, 'utf8').trim(); - if (!body) return; - - const prNumber = ${{ inputs.pr-id || 0 }}; - if (!prNumber) { - core.warning('Could not determine PR number, skipping dependency comment'); - return; - } - - const marker = '<!-- ci-parent-pom-deps -->'; - - try { - const { data: comments } = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - }); - const existing = comments.find(c => c.body && c.body.includes(marker)); - - if (existing) { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existing.id, - body: body, - }); - } else { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: body, - }); - } - } catch (error) { - core.warning(`Failed to post dependency change comment: ${error.message}`); - } + run: ${{ github.action_path }}/detect-test.sh ${{ inputs.base-ref || github.base_ref }} ${{ steps.install-mvnd.outputs.mvnd-dir }}/mvnd diff --git a/.github/actions/detect-dependencies/detect-test.sh b/.github/actions/detect-dependencies/detect-test.sh index 2f55e1c2f918..dcdb3a9e218f 100755 --- a/.github/actions/detect-dependencies/detect-test.sh +++ b/.github/actions/detect-dependencies/detect-test.sh @@ -15,381 +15,82 @@ # limitations under the License. # -# Detects property changes in parent/pom.xml, maps them to the managed -# artifacts that use those properties, then uses Maveniverse Toolbox to -# find which modules depend on those artifacts (including transitive -# dependencies) and runs their tests. -# -# Uses the GitHub API to fetch the PR diff (works with shallow clones). -# -# Approach: -# 1. Fetch PR diff via GitHub API, extract parent/pom.xml changes -# 2. Find changed property names from the diff -# 3. Parse parent/pom.xml to map property -> groupId:artifactId -# (detecting BOM imports vs regular dependencies) -# 4. Use toolbox:tree-find to find all modules depending on those -# artifacts (direct + transitive) -# 5. Run tests for affected modules - set -euo pipefail -MAX_MODULES=50 -TOOLBOX_PLUGIN="eu.maveniverse.maven.plugins:toolbox" - -# Fetch the PR diff from the GitHub API and extract only the parent/pom.xml -# portion. Returns the unified diff for parent/pom.xml, or empty if not changed. -fetch_parent_pom_diff() { - local pr_id="$1" - local repository="$2" - - local diff_output - diff_output=$(curl -s -w "\n%{http_code}" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "Accept: application/vnd.github.v3.diff" \ - "https://api.github.com/repos/${repository}/pulls/${pr_id}") - - local http_code - http_code=$(echo "$diff_output" | tail -n 1) - local diff_body - diff_body=$(echo "$diff_output" | sed '$d') - - if [[ "$http_code" -lt 200 || "$http_code" -ge 300 || -z "$diff_body" ]]; then - echo "WARNING: Failed to fetch PR diff (HTTP $http_code)" >&2 - return - fi - - # Extract only the parent/pom.xml diff section - echo "$diff_body" | awk ' - /^diff --git/ && found { exit } - /^diff --git a\/parent\/pom.xml/ { found=1 } - found { print } - ' -} - -# Detect which properties changed in the parent/pom.xml diff. -# Returns one property name per line. detect_changed_properties() { - local diff_content="$1" + local base_branch="$1" - echo "$diff_content" | \ - grep -E '^[+-][[:space:]]*<[^>]+>[^<]*</[^>]+>' | \ - grep -vE '^\+\+\+|^---' | \ - sed -E 's/^[+-][[:space:]]*<([^>]+)>.*/\1/' | \ + git diff "${base_branch}" -- parent/pom.xml | \ + grep -E '^[+-]\s*<[^>]+>[^<]*</[^>]+>' | \ + grep -vE '^\+\+\+|---' | \ + grep -E 'version|dependency|artifact' | \ + sed -E 's/^[+-]\s*<([^>]+)>.*/\1/' | \ sort -u || true } -# Given a property name, find which groupId:artifactId pairs in -# parent/pom.xml use it as their <version>. -# Also detects if the artifact is a BOM import (<type>pom</type> + -# <scope>import</scope>), in which case it outputs "bom:groupId" -# so the caller can search by groupId wildcard. -# Returns one entry per line: either "groupId:artifactId" or "bom:groupId". -find_gav_for_property() { - local property="$1" - local parent_pom="parent/pom.xml" - - local matches - matches=$(grep -n "<version>\${${property}}</version>" "$parent_pom" 2>/dev/null || true) - - if [ -z "$matches" ]; then - return - fi - - echo "$matches" | while IFS=: read -r line_num _; do - local block - block=$(sed -n "1,${line_num}p" "$parent_pom") - local artifactId - artifactId=$(echo "$block" | grep '<artifactId>' | tail -1 | sed 's/.*<artifactId>\([^<]*\)<\/artifactId>.*/\1/') - local groupId - groupId=$(echo "$block" | grep '<groupId>' | tail -1 | sed 's/.*<groupId>\([^<]*\)<\/groupId>.*/\1/') - - # Check if this is a BOM import by looking at lines after the version - local after_version - after_version=$(sed -n "$((line_num+1)),$((line_num+3))p" "$parent_pom") - if echo "$after_version" | grep -q '<type>pom</type>' && echo "$after_version" | grep -q '<scope>import</scope>'; then - echo "bom:${groupId}" - else - echo "${groupId}:${artifactId}" +find_affected_modules() { + local property_name="$1" + local mavenBinary=${2} + local affected=() + + while IFS= read -r pom; do + # skip any target that may have been built previously + if [[ "$pom" != */target/* ]]; then + # only consider certain modules, nothing else + if [[ "$pom" == */catalog/* ]] || \ + [[ "$pom" == */components/* ]] || \ + [[ "$pom" == */core/* ]] || \ + ([[ "$pom" == */dsl/* ]] && [[ "$pom" != */dsl/camel-jbang* ]]); then + if grep -q "\${${property_name}}" "$pom"; then + affected+=("$pom") + fi + fi fi - done | sort -u -} - -# Use Maveniverse Toolbox tree-find to discover all modules that depend -# on a given artifact (including transitive dependencies). -# Returns one module artifactId per line. -find_modules_with_toolbox() { - local mavenBinary="$1" - local matcher_spec="$2" - local search_pattern="$3" + done < <(find . -name "pom.xml") - local output - output=$($mavenBinary -B ${TOOLBOX_PLUGIN}:tree-find \ - -DartifactMatcherSpec="${matcher_spec}" 2>&1 || true) + affected_transformed="" - if echo "$output" | grep -q 'BUILD FAILURE'; then - echo " WARNING: toolbox tree-find failed, skipping" >&2 - return - fi + for pom in "${affected[@]}"; do + if [[ -f "$pom" ]]; then + artifactId=$($mavenBinary -f "$pom" help:evaluate -Dexpression=project.artifactId -q --raw-streams -DforceStdout) + if [ ! -z "$artifactId" ]; then + affected_transformed+=":$artifactId," + fi + fi + done - # Parse output: track current module from "Paths found in project" lines, - # then when a dependency match is found, output that module's artifactId. - # Note: mvnd strips [module] prefixes when output is captured to a - # variable, so we track the current module from "Paths found" headers. - echo "$output" | awk -v pattern="$search_pattern" ' - /Paths found in project/ { - split($0, a, "project ") - split(a[2], b, ":") - current = b[2] - } - index($0, pattern) && /->/ { - print current - } - ' | sort -u + echo "$affected_transformed" } main() { echo "Using MVND_OPTS=$MVND_OPTS" - local mavenBinary=${1} - local prId=${2} - local repository=${3} - local log="detect-dependencies.log" - local exclusionList="!:camel-allcomponents,!:dummy-component,!:camel-catalog,!:camel-catalog-console,!:camel-catalog-lucene,!:camel-catalog-maven,!:camel-catalog-suggest,!:camel-route-parser,!:camel-csimple-maven-plugin,!:camel-report-maven-plugin,!:camel-endpointdsl,!:camel-componentdsl,!:camel-endpointdsl-support,!:camel-yaml-dsl,!:camel-kamelet-main,!:camel-yaml-dsl-deserializers,!:camel-yaml-dsl-maven-plugin,!:camel-jbang-core,!:camel-jbang-main,!:camel-jbang-plugin-generate,!:came [...] + local base_branch=${1} + local mavenBinary=${2} + local exclusionList="!:camel-allcomponents,!:dummy-component,!:camel-catalog,!:camel-catalog-console,!:camel-catalog-lucene,!:camel-catalog-maven,!:camel-catalog-suggest,!:camel-route-parser,!:camel-csimple-maven-plugin,!:camel-report-maven-plugin,!:camel-endpointdsl,!:camel-componentdsl,!:camel-endpointdsl-support,!:camel-yaml-dsl,!:camel-kamelet-main,!:camel-yaml-dsl-deserializers,!:camel-yaml-dsl-maven-plugin,!:camel-jbang-core,!:camel-jbang-main,!:camel-jbang-plugin-generate,!:came [...] - # Fetch diff via GitHub API (works with shallow clones) - echo "Fetching PR #${prId} diff from GitHub API..." - local parent_diff - parent_diff=$(fetch_parent_pom_diff "$prId" "$repository") + git fetch origin $base_branch:$base_branch - if [ -z "$parent_diff" ]; then - echo "parent/pom.xml not changed, nothing to do" - exit 0 - fi - - local changed_props - changed_props=$(detect_changed_properties "$parent_diff") + changed_props=$(detect_changed_properties "$base_branch") if [ -z "$changed_props" ]; then - echo "No property changes detected in parent/pom.xml" + echo "โ No property changes detected." exit 0 fi - echo "Changed properties in parent/pom.xml:" - echo "$changed_props" - echo "" + modules_affected="" - # Map properties -> GAV coordinates for toolbox lookup - # For properties not used in parent's dependencyManagement, fall back - # to grepping for ${property} in module pom.xml files directly - local all_gavs="" - local fallback_props="" while read -r prop; do - [ -z "$prop" ] && continue - - local gavs - gavs=$(find_gav_for_property "$prop") - if [ -z "$gavs" ]; then - echo " Property '$prop': not in dependencyManagement, will search modules directly" - fallback_props="${fallback_props:+${fallback_props} -}${prop}" - continue - fi - - echo " Property '$prop' manages:" - while read -r gav; do - [ -z "$gav" ] && continue - echo " - $gav" - all_gavs="${all_gavs:+${all_gavs} -}${gav}" - done <<< "$gavs" + modules=$(find_affected_modules "$prop" $mavenBinary) + modules_affected+="$modules" done <<< "$changed_props" - if [ -z "$all_gavs" ] && [ -z "$fallback_props" ]; then - echo "" - echo "No managed artifacts found for changed properties" + if [ -z "$modules_affected" ]; then + echo "โ No components affected by property changes detected." exit 0 fi - local all_module_ids="" - local seen_modules="" - - # Step 1: Use Toolbox tree-find for properties with managed artifacts - if [ -n "$all_gavs" ]; then - echo "" - echo "Searching for affected modules using Maveniverse Toolbox..." - - local unique_gavs - unique_gavs=$(echo "$all_gavs" | sort -u) - - while read -r gav; do - [ -z "$gav" ] && continue - - local matcher_spec search_pattern - if [[ "$gav" == bom:* ]]; then - # BOM import: search by groupId wildcard - local groupId="${gav#bom:}" - matcher_spec="artifact(${groupId}:*)" - search_pattern="${groupId}:" - echo " Searching for modules using ${groupId}:* (BOM)..." - else - matcher_spec="artifact(${gav})" - search_pattern="${gav}" - echo " Searching for modules using ${gav}..." - fi - - local modules - modules=$(find_modules_with_toolbox "$mavenBinary" "$matcher_spec" "$search_pattern") - if [ -n "$modules" ]; then - while read -r mod; do - [ -z "$mod" ] && continue - if ! echo "$seen_modules" | grep -qx "$mod"; then - seen_modules="${seen_modules:+${seen_modules} -}${mod}" - all_module_ids="${all_module_ids:+${all_module_ids},}:${mod}" - fi - done <<< "$modules" - fi - done <<< "$unique_gavs" - fi - - # Step 2: Fallback for properties used directly in module pom.xml files - # (not through parent's dependencyManagement) - if [ -n "$fallback_props" ]; then - echo "" - echo "Searching for modules referencing properties directly..." - - while read -r prop; do - [ -z "$prop" ] && continue - - local matches - matches=$(grep -rl "\${${prop}}" --include="pom.xml" . 2>/dev/null | \ - grep -v "^\./parent/pom.xml" | \ - grep -v "/target/" | \ - grep -v "\.claude/worktrees" || true) - - if [ -n "$matches" ]; then - echo " Property '\${${prop}}' referenced by:" - while read -r pom_file; do - [ -z "$pom_file" ] && continue - # Extract artifactId from the module's pom.xml - local mod_artifact - mod_artifact=$(sed -n '/<parent>/,/<\/parent>/!{ s/.*<artifactId>\([^<]*\)<\/artifactId>.*/\1/p }' "$pom_file" | head -1) - if [ -n "$mod_artifact" ] && ! echo "$seen_modules" | grep -qx "$mod_artifact"; then - echo " - $mod_artifact" - seen_modules="${seen_modules:+${seen_modules} -}${mod_artifact}" - all_module_ids="${all_module_ids:+${all_module_ids},}:${mod_artifact}" - fi - done <<< "$matches" - fi - done <<< "$fallback_props" - fi - - if [ -z "$all_module_ids" ]; then - echo "" - echo "No modules depend on the changed artifacts" - exit 0 - fi - - # Count modules - local module_count - module_count=$(echo "$all_module_ids" | tr ',' '\n' | wc -l | tr -d ' ') - - echo "" - echo "Found ${module_count} modules affected by parent/pom.xml property changes:" - echo "$all_module_ids" | tr ',' '\n' | while read -r m; do - echo " - $m" - done - echo "" - - if [ "${module_count}" -gt "${MAX_MODULES}" ]; then - echo "Too many affected modules (${module_count} > ${MAX_MODULES}), skipping targeted tests" - - write_comment "$changed_props" "$all_module_ids" "$module_count" "skip" - exit 0 - fi - - # Filter out modules that are in the exclusion list - local filtered_ids="" - local IFS_backup="$IFS" - IFS=',' - for mod_id in $all_module_ids; do - if ! echo ",$exclusionList," | grep -q ",!${mod_id},"; then - filtered_ids="${filtered_ids:+${filtered_ids},}${mod_id}" - else - echo " Skipping excluded module: $mod_id" - fi - done - IFS="$IFS_backup" - - if [ -z "$filtered_ids" ]; then - echo "All affected modules are in the exclusion list, skipping targeted tests" - write_comment "$changed_props" "$all_module_ids" "$module_count" "skip" - exit 0 - fi - - echo "Running targeted tests for affected modules..." - # Use install instead of test, otherwise test-infra modules fail due to jandex maven plugin - $mavenBinary -l $log $MVND_OPTS install -pl "${filtered_ids},${exclusionList}" -amd - local ret=$? - - if [ ${ret} -eq 0 ]; then - write_comment "$changed_props" "$all_module_ids" "$module_count" "pass" - else - write_comment "$changed_props" "$all_module_ids" "$module_count" "fail" - fi - - # Write step summary - if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then - echo "### Parent POM dependency change tests" >> "$GITHUB_STEP_SUMMARY" - echo "" >> "$GITHUB_STEP_SUMMARY" - echo "Changed properties: $(echo "$changed_props" | tr '\n' ', ' | sed 's/,$//')" >> "$GITHUB_STEP_SUMMARY" - echo "" >> "$GITHUB_STEP_SUMMARY" - echo "$all_module_ids" | tr ',' '\n' | while read -r m; do - echo "- \`$m\`" >> "$GITHUB_STEP_SUMMARY" - done - - if [ ${ret} -ne 0 ]; then - echo "" >> "$GITHUB_STEP_SUMMARY" - echo "Processing surefire and failsafe reports to create the summary" >> "$GITHUB_STEP_SUMMARY" - echo -e "| Failed Test | Duration | Failure Type |\n| --- | --- | --- |" >> "$GITHUB_STEP_SUMMARY" - find . -path '*target/*-reports*' -iname '*.txt' -exec .github/actions/incremental-build/parse_errors.sh {} \; - fi - fi - - exit $ret -} - -write_comment() { - local changed_props="$1" - local modules="$2" - local module_count="$3" - local status="$4" - local comment_file="detect-dependencies-comment.md" - - echo "<!-- ci-parent-pom-deps -->" > "$comment_file" - - case "$status" in - pass) - echo ":white_check_mark: **Parent POM dependency changes: targeted tests passed**" >> "$comment_file" - ;; - fail) - echo ":x: **Parent POM dependency changes: targeted tests failed**" >> "$comment_file" - ;; - skip) - echo ":information_source: **Parent POM dependency changes detected** but too many modules affected (${module_count}) to run targeted tests." >> "$comment_file" - ;; - esac - - echo "" >> "$comment_file" - echo "Changed properties: $(echo "$changed_props" | tr '\n' ', ' | sed 's/,$//')" >> "$comment_file" - echo "" >> "$comment_file" - echo "<details><summary>Affected modules (${module_count})</summary>" >> "$comment_file" - echo "" >> "$comment_file" - echo "$modules" | tr ',' '\n' | while read -r m; do - echo "- \`$m\`" >> "$comment_file" - done - echo "" >> "$comment_file" - echo "</details>" >> "$comment_file" + echo "๐งช Testing the following modules $modules_affected and its dependents" + $mavenBinary $MVND_OPTS test -pl "$modules_affected$exclusionList" -amd } main "$@" diff --git a/.github/workflows/pr-build-main.yml b/.github/workflows/pr-build-main.yml index fe32bbacbf7a..539a1250555c 100644 --- a/.github/workflows/pr-build-main.yml +++ b/.github/workflows/pr-build-main.yml @@ -143,10 +143,7 @@ jobs: core.warning(`Failed to post CI test summary comment: ${error.message}`); } - name: mvn test parent pom dependencies changed - if: always() && !matrix.experimental uses: ./.github/actions/detect-dependencies with: github-token: ${{ secrets.GITHUB_TOKEN }} - pr-id: ${{ github.event.number || inputs.pr_number }} - github-repo: ${{ github.repository }} - skip-mvnd-install: 'true' + base-ref: ${{ github.base_ref || 'main' }}
