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()