This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new ac20afcc76 Add GitHub workflow to perform dependency convergence checks
ac20afcc76 is described below

commit ac20afcc763759019f8e47a92fa984d5e8251025
Author: James Netherton <jamesnether...@gmail.com>
AuthorDate: Tue May 6 09:22:52 2025 +0100

    Add GitHub workflow to perform dependency convergence checks
    
    Fixes #5196
---
 .github/workflows/check-dependency-convergence.yml | 177 +++++++++++++++++++++
 .github/workflows/ci-build.yaml                    |   1 +
 .github/workflows/pr-validate.yml                  |   1 +
 tooling/scripts/create-superapp.groovy             |  97 +++++++++++
 4 files changed, 276 insertions(+)

diff --git a/.github/workflows/check-dependency-convergence.yml 
b/.github/workflows/check-dependency-convergence.yml
new file mode 100644
index 0000000000..f6aa985ac3
--- /dev/null
+++ b/.github/workflows/check-dependency-convergence.yml
@@ -0,0 +1,177 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: Check Dependency Convergence
+
+on:
+  schedule:
+    # Run every sunday at 12PM
+    - cron: '0 12 * * 0'
+  workflow_dispatch:
+
+concurrency:
+  group: ${{ github.ref }}-${{ github.workflow }}
+  cancel-in-progress: true
+
+env:
+  LANG: en_US.UTF-8
+  MAVEN_OPTS: -Xmx3000m
+  CQ_MAVEN_ARGS: -V -ntp -e -Daether.connector.http.connectionMaxTtl=120
+  ISSUE_ID: 7348
+
+jobs:
+  check-dependency-convergence:
+    if: github.repository == 'apache/camel-quarkus'
+    runs-on: ubuntu-latest
+    permissions:
+      issues: write
+    steps:
+      - name: Set up JDK 17
+        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # 
v4.7.1
+        with:
+          distribution: 'temurin'
+          java-version: '17'
+      - name: Checkout
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 
v4.2.2
+      - name: Set Build Info
+        run: |
+          [ ! -d ~/build-data ] && mkdir -p ~/build-data
+          echo "${{ github.run_id }}-${{ github.run_number }}-$(uuidgen)" > 
~/build-data/build-id.txt
+          git rev-parse HEAD > ~/build-data/main-sha.txt
+      - name: Build Camel Quarkus
+        run: ./mvnw ${CQ_MAVEN_ARGS} clean install -Dquickly -T1C
+      - name: Install Groovy
+        run:
+          sudo apt install groovy --no-install-recommends -y
+      - name: Create Superapp
+        run: |
+          groovy tooling/scripts/create-superapp.groovy
+      - name: Run checks
+        run: |
+          # Copy maven wrapper
+          cp -r .mvn ${{ runner.temp }}/camel-quarkus-superapp/
+          cp ./mvnw ${{ runner.temp }}/camel-quarkus-superapp/
+          
+          # Run dependency convergence checks
+          cd ${{ runner.temp }}/camel-quarkus-superapp/
+          ./mvnw ${CQ_MAVEN_ARGS} validate -Denforcer.fail=false | tee -a 
enforcer.log
+      - name: Analyze Results
+        run: |
+          INPUT_FILE="${{ runner.temp }}/camel-quarkus-superapp/enforcer.log"
+          OUTPUT_FILE="${{ runner.temp 
}}/camel-quarkus-superapp/enforcer-filtered.log"
+
+          # Clean up enforcer output
+          sed -i '1,/Failed while enforcing releasability./d' ${INPUT_FILE}
+
+          # List of Maven GAVs to ignore from the dependency convergence check 
results. Keep sorted alphabetically
+          IGNORED_GAVS=(
+            # Mismatch between camel-quarkus-aws-xray & 
camel-quarkus-aws2-kinesis
+            "com.amazonaws:aws-java-sdk-core"
+            # Mismatch between camel-quarkus-aws-xray & 
camel-quarkus-aws2-kinesis
+            "com.amazonaws:jmespath-java"
+            # Mismatch between camel-quarkus-grpc & camel-quarkus-twilio
+            "com.auth0:java-jwt"
+            # Mismatch between camel-quarkus-cassandraql & camel-quarkus-web3j
+            "com.github.jnr:jnr-posix"
+            # Mismatch between camel-quarkus-google-bigquery, 
camel-quarkus-google-functions, camel-quarkus-google-pubsub & 
camel-quarkus-google-storage
+            "com.google.api-client:google-api-client"
+            # Mismatch between camel-quarkus-google-bigquery, 
camel-quarkus-google-functions, camel-quarkus-google-pubsub & 
camel-quarkus-google-storage
+            "com.google.api:api-common"
+            # Mismatch between camel-quarkus-google-bigquery, 
camel-quarkus-google-functions, camel-quarkus-google-pubsub & 
camel-quarkus-google-storage
+            "com.google.api:gax"
+            # Mismatch between camel-quarkus-google-bigquery, 
camel-quarkus-google-functions, camel-quarkus-google-pubsub & 
camel-quarkus-google-storage
+            "com.google.api:gax-grpc"
+            # Mismatch between camel-quarkus-google-bigquery, 
camel-quarkus-google-functions, camel-quarkus-google-pubsub & 
camel-quarkus-google-storage
+            "com.google.api.grpc:proto-google-iam-v1"
+            # Mismatch between camel-quarkus-couchdb & 
camel-quarkus-ibm-secrets-manager
+            "com.ibm.cloud:sdk-core"
+            # Mismatch between camel-quarkus-cassandraql & camel-quarkus-dfdl
+            "com.typesafe:config"
+            # Mismatch between camel-quarkus-aws-datasonnet, camel-quarkus-djl 
& camel-quarkus-aws2-kinesis
+            "io.github.classgraph:classgraph"
+            # Mismatch between camel-quarkus-csv, camel-quarkus-djl & 
camel-quarkus-tika
+            "org.apache.commons:commons-csv"
+            # Mismatch between camel-quarkus-ldif, camel-quarkus-milvus, 
camel-quarkus-netty & camel-quarkus-spring-redis
+            "org.apache.commons:commons-pool2"
+            # Mismatch between camel-quarkus-jsch, camel-quarkus-ldif & 
camel-quarkus-quickfix
+            "org.apache.mina:mina-core"
+            # Mismatch between camel-quarkus-as2, 
camel-quarkus-avro-deployment & camel-quarkus-cxf-soap-deployment
+            "org.apache.velocity:velocity-engine-core"
+            # Mismatch between camel-quarkus-jcr & camel-quarkus-tika
+            "org.apache.tika:tika-core"
+            # Mismatch between camel-quarkus-rest-openapi-deployment & 
camel-quarkus-smallrye-reactive-messaging-deployment
+            "org.commonmark:commonmark"
+            # Mismatch between camel-quarkus-activemq & camel-quarkus-stomp
+            "org.fusesource.hawtbuf:hawtbuf"
+            # Mismatch between camel-quarkus-aws2-kinesis & 
camel-quarkus-pubnub
+            "org.jetbrains.kotlinx:kotlinx-datetime-jvm"
+            # Mismatch between camel-quarkus-aws2-jgroups & 
camel-quarkus-jgroups-raft
+            "org.jgroups:jgroups"
+            # Mismatch between camel-quarkus-box, camel-quarkus-oaipmh & 
camel-quarkus-shiro
+            "org.jsoup:jsoup"
+            # Mismatch between camel-quarkus-jcr & camel-quarkus-lucene
+            "org.apache.lucene:lucene-core"
+            # Mismatch between camel-quarkus-flink, camel-quarkus-junit5, 
camel-quarkus-nitrite & camel-quarkus-redis
+            "org.objenesis:objenesis"
+          )
+
+          BLOCK=""
+          IN_BLOCK=false
+          KEEP_BLOCK=true
+
+          # Filter out errors for ignored GAVs
+          while IFS= read -r LINE || [[ -n "${LINE}" ]]; do
+            if [[ "${LINE}" =~ ^Dependency\ convergence\ error\ for\ 
([^:]+:[^:]+): ]]; then
+              if ${IN_BLOCK} && ${KEEP_BLOCK}; then
+                echo "${BLOCK}" >> ${OUTPUT_FILE}
+              fi
+
+              BLOCK="${LINE}"
+              IN_BLOCK=true
+              KEEP_BLOCK=true
+              GAV="${BASH_REMATCH[1]}"
+
+              for IGNORED in "${IGNORED_GAVS[@]}"; do
+                if [[ "${GAV}" == "${IGNORED}" ]]; then
+                  KEEP_BLOCK=false
+                  break
+                fi
+              done
+            elif ${IN_BLOCK}; then
+              BLOCK+=$'\n'"${LINE}"
+            else
+              echo "${LINE}" >> ${OUTPUT_FILE}
+            fi
+          done < ${INPUT_FILE}
+
+          if ${IN_BLOCK} && ${KEEP_BLOCK}; then
+            echo "${BLOCK}" >> ${OUTPUT_FILE}
+          fi
+
+          # If after excluding ignored GAVs there are still convergence check 
errors, fail the build
+          if grep "Dependency convergence error" ${OUTPUT_FILE} > /dev/null; 
then
+            echo "There are dependency convergence errors!"
+            echo
+            cat ${OUTPUT_FILE}
+            echo
+            echo "Either fix the problem dependencies or add GAVs to the 
IGNORED_GAVS list in check-dependency-convergence.yml"
+            exit 1
+          fi
+      - name: Report Build Failure
+        if: failure() || cancelled()
+        run: |
+          ./mvnw ${CQ_MAVEN_ARGS} verify -N -Pbuild-notification -Dstatus=${{ 
job.status }} -DissueId=${{ env.ISSUE_ID }} -Dtoken=${{ secrets.GITHUB_TOKEN }} 
-DbuildId=$(cat ~/build-data/build-id.txt) -Drepo=${GITHUB_REPOSITORY} 
-Dbranch=$(git rev-parse --abbrev-ref HEAD) -Dbranch-commit=$(cat 
~/build-data/main-sha.txt)
diff --git a/.github/workflows/ci-build.yaml b/.github/workflows/ci-build.yaml
index 03e8569b2a..299b9f8b3b 100644
--- a/.github/workflows/ci-build.yaml
+++ b/.github/workflows/ci-build.yaml
@@ -39,6 +39,7 @@ on:
       - '.github/workflows/assign-issue-milestone.yaml'
       - '.github/workflows/assign-wontfix-issue-milestone.yaml'
       - '.github/workflows/camel-master-cron.yaml'
+      - '.github/workflows/check-dependency-convergence.yml'
       - '.github/workflows/generate-sbom-main.yml'
       - '.github/workflows/label-issue.yaml'
       - '.github/workflows/pr-validate.yml'
diff --git a/.github/workflows/pr-validate.yml 
b/.github/workflows/pr-validate.yml
index 803de90937..80a2c0830b 100644
--- a/.github/workflows/pr-validate.yml
+++ b/.github/workflows/pr-validate.yml
@@ -38,6 +38,7 @@ on:
       - '.github/workflows/assign-issue-milestone.yaml'
       - '.github/workflows/assign-wontfix-issue-milestone.yaml'
       - '.github/workflows/camel-master-cron.yaml'
+      - '.github/workflows/check-dependency-convergence.yml'
       - '.github/workflows/generate-sbom-main.yml'
       - '.github/workflows/label-issue.yaml'
       - '.github/workflows/pr-validate.yml'
diff --git a/tooling/scripts/create-superapp.groovy 
b/tooling/scripts/create-superapp.groovy
new file mode 100644
index 0000000000..c92f68761b
--- /dev/null
+++ b/tooling/scripts/create-superapp.groovy
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import groovy.xml.*
+
+def rootPom = new XmlParser().parse(new File('pom.xml'))
+def camelQuarkusVersion = rootPom.version.text()
+def quarkusVersion = rootPom.properties.'quarkus.version'?.text()
+def mavenEnforcerPluginVersion = 
rootPom.properties.'maven-enforcer-plugin.version'?.text()
+
+// Get org.apache.camel.quarkus dependencies from camel-quarkus-bom
+def cqBomPath = 
"${System.properties['user.home']}/.m2/repository/org/apache/camel/quarkus/camel-quarkus-bom/${camelQuarkusVersion}/camel-quarkus-bom-${camelQuarkusVersion}.pom"
+def bom = new XmlParser().parse(new File(cqBomPath))
+def cqBomDependencies = 
bom.dependencyManagement.dependencies?.dependency?.findAll {
+    it.groupId.text().startsWith('org.apache.camel.quarkus') && 
!it.artifactId.text().contains("-support") && 
it.artifactId.text().endsWith('-deployment')
+}
+
+// Create a 'super' POM with all camel-quarkus-* dependencies
+def writer = new StringWriter()
+def xml = new MarkupBuilder(writer)
+
+xml.project(xmlns: "http://maven.apache.org/POM/4.0.0";,
+        "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance";,
+        "xsi:schemaLocation": "http://maven.apache.org/POM/4.0.0 
https://maven.apache.org/xsd/maven-4.0.0.xsd";) {
+    modelVersion('4.0.0')
+    groupId('org.apache.camel.quarkus')
+    artifactId('camel-quarkus-superapp')
+    version(camelQuarkusVersion)
+    packaging('pom')
+    build {
+        plugins {
+            plugin {
+                groupId('org.apache.maven.plugins')
+                artifactId('maven-enforcer-plugin')
+                version(mavenEnforcerPluginVersion)
+                executions {
+                    execution {
+                        goals {
+                            goal('enforce')
+                        }
+                        configuration {
+                            rules {
+                                dependencyConvergence()
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    dependencyManagement {
+        dependencies {
+            dependency{
+                groupId('io.quarkus')
+                artifactId('quarkus-bom')
+                version(quarkusVersion)
+                type('pom')
+                scope('import')
+            }
+            dependency{
+                groupId('org.apache.camel.quarkus')
+                artifactId('camel-quarkus-bom')
+                version(camelQuarkusVersion)
+                type('pom')
+                scope('import')
+            }
+        }
+    }
+    dependencies {
+        cqBomDependencies.each { dep ->
+            dependency {
+                groupId(dep.groupId.text())
+                artifactId(dep.artifactId.text().replace("-deployment", ""))
+            }
+        }
+    }
+}
+
+def tmp = System.getenv('RUNNER_TEMP')
+def superAppDir = new File("${tmp}/camel-quarkus-superapp")
+superAppDir.mkdirs()
+
+new File("${superAppDir}/pom.xml").text = writer.toString()

Reply via email to