| # |
| # 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: Test |
| |
| on: |
| workflow_dispatch: |
| pull_request: |
| |
| concurrency: |
| group: unit-test-${{ github.event.pull_request.number || github.ref }} |
| cancel-in-progress: true |
| |
| jobs: |
| paths-filter: |
| name: Unit-Test-Path-Filter |
| runs-on: ubuntu-latest |
| outputs: |
| not-ignore: ${{ steps.filter.outputs.not-ignore }} |
| steps: |
| - uses: actions/checkout@v6 |
| with: |
| submodules: true |
| - uses: ./.github/actions/paths-filter |
| id: filter |
| with: |
| filters: | |
| not-ignore: |
| - '!(docs/**)' |
| |
| sanity-check: |
| name: Sanity Check |
| runs-on: ubuntu-latest |
| needs: paths-filter |
| if: ${{ needs.paths-filter.outputs.not-ignore == 'true' }} |
| steps: |
| - uses: actions/checkout@v6 |
| with: |
| submodules: true |
| - name: Sanity Check |
| uses: ./.github/actions/sanity-check |
| with: |
| token: ${{ secrets.GITHUB_TOKEN }} |
| |
| generate-matrix: |
| name: Generate Module Matrix |
| runs-on: ubuntu-latest |
| needs: paths-filter |
| if: ${{ needs.paths-filter.outputs.not-ignore == 'true' }} |
| outputs: |
| matrix: ${{ steps.set-matrix.outputs.matrix }} |
| steps: |
| - uses: actions/checkout@v6 |
| |
| - name: Parse modules from pom.xml |
| id: set-matrix |
| run: | |
| MODULES=$(python3 - <<'EOF' |
| import xml.etree.ElementTree as ET, json, re |
| |
| tree = ET.parse('pom.xml') |
| ns = {'m': 'http://maven.apache.org/POM/4.0.0'} |
| root = tree.getroot() |
| |
| # Support both namespaced and non-namespaced pom.xml |
| modules = root.findall('.//m:modules/m:module', ns) |
| if not modules: |
| modules = root.findall('.//modules/module') |
| |
| # Exclude aggregator-only or non-testable modules |
| exclude = re.compile(r'dolphinscheduler-bom|dolphinscheduler-dist|dolphinscheduler-microbench|dolphinscheduler-ui') |
| result = [m.text.strip() for m in modules if m.text and not exclude.search(m.text)] |
| print(json.dumps(result)) |
| EOF |
| ) |
| |
| echo "matrix={\"module\":$MODULES}" >> "$GITHUB_OUTPUT" |
| echo "Discovered modules: $MODULES" |
| |
| unit-test: |
| name: Unit-Test (${{ matrix.module }} | Java ${{ matrix.java }}) |
| needs: [ paths-filter, generate-matrix, sanity-check ] |
| if: ${{ needs.paths-filter.outputs.not-ignore == 'true' }} |
| runs-on: ubuntu-latest |
| strategy: |
| matrix: |
| java: [ '8', '11' ] |
| module: ${{ fromJSON(needs.generate-matrix.outputs.matrix).module }} |
| timeout-minutes: 60 |
| steps: |
| - uses: actions/checkout@v6 |
| with: |
| submodules: true |
| |
| - name: Collect Workflow Metrics |
| uses: ./.github/actions/actions-workflow-metrics |
| |
| - name: Set up JDK ${{ matrix.java }} |
| uses: actions/setup-java@v5 |
| with: |
| java-version: ${{ matrix.java }} |
| distribution: 'adopt' |
| |
| - uses: actions/cache@v5 |
| with: |
| path: ~/.m2/repository |
| key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-backend |
| restore-keys: ${{ runner.os }}-maven- |
| |
| # Install the target module and its upstream dependencies into the local |
| # Maven repository without running tests. Use skipTests instead of |
| # maven.test.skip so packaging still sees provided-scope dependencies and |
| # attaches any test/provided artifacts required by downstream modules. |
| - name: Install Dependencies (${{ matrix.module }}) |
| run: | |
| export MAVEN_OPTS="-Xmx14g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=1024m" |
| ./mvnw install -B \ |
| -pl "dolphinscheduler-bom,${{ matrix.module }}" \ |
| -am \ |
| -DskipTests=true \ |
| -Dspotless.skip=true \ |
| -DskipUT=true \ |
| -Djacoco.skip=true \ |
| -Danalyze.skip=true |
| |
| # Verify only the target module. Do not use -am here, otherwise Maven |
| # will run the verify lifecycle for dependency modules too. |
| - name: Run Unit Tests (${{ matrix.module }}) |
| run: | |
| export MAVEN_OPTS="-Xmx14g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=1024m" |
| ./mvnw verify -B \ |
| -pl "${{ matrix.module }}" \ |
| -Dmaven.test.skip=false \ |
| -Dspotless.skip=true \ |
| -DskipUT=false \ |
| -Danalyze.skip=true \ |
| -Dsurefire.printSummary=true \ |
| -Dsurefire.useFile=false \ |
| -Dsurefire.reportFormat=plain \ |
| -Dsurefire.redirectTestOutputToFile=false |
| |
| - name: Upload surefire reports |
| uses: actions/upload-artifact@v6 |
| if: always() |
| with: |
| name: surefire-java${{ matrix.java }}-${{ matrix.module }} |
| path: '**/target/surefire-reports/' |
| retention-days: 7 |
| |
| result: |
| name: Unit Test |
| runs-on: ubuntu-latest |
| timeout-minutes: 5 |
| needs: [ unit-test, paths-filter, sanity-check ] |
| if: always() |
| steps: |
| - name: Status |
| run: | |
| if [[ ${{ needs.paths-filter.outputs.not-ignore }} == 'false' && ${{ github.event_name }} == 'pull_request' ]]; then |
| echo "Skip Unit Test!" |
| exit 0 |
| fi |
| if [[ ${{ needs.sanity-check.result }} != 'success' ]]; then |
| echo "Sanity Check Failed!" |
| exit -1 |
| fi |
| if [[ ${{ needs.unit-test.result }} != 'success' ]]; then |
| echo "Unit Test Failed!" |
| exit -1 |
| fi |