Performance benchmarks: measurement scripts and analysis docs (#272) … #612
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time | |
| # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven | |
| # This workflow uses actions that are not certified by GitHub. | |
| # They are provided by a third-party and are governed by | |
| # separate terms of service, privacy policy, and support | |
| # documentation. | |
| name: Java CI with Maven | |
| on: | |
| push: | |
| branches: [ "main" ] | |
| pull_request: | |
| branches: [ "main" ] | |
| types: [opened, synchronize, reopened] | |
| workflow_dispatch: | |
| # Cancel superseded runs for the same ref to save runner minutes. | |
| concurrency: | |
| group: maven-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| # Least privilege: read the repository (checkout + build) and write | |
| # check-run output (test/analysis results). No step uses the workflow | |
| # token to write to pull requests. | |
| permissions: | |
| contents: read | |
| checks: write | |
| # Expose secret-backed tokens as env so steps can be gated on their | |
| # availability. On fork/Dependabot PRs secrets are withheld and resolve to | |
| # an empty string, so the dependent steps are skipped rather than failing. | |
| env: | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 # Shallow clones should be disabled for better SonarCloud analysis | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0 | |
| with: | |
| java-version: '17' | |
| distribution: 'zulu' | |
| cache: maven | |
| - name: Cache SonarCloud packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.sonar/cache | |
| # Content-addressed so the cache rotates when project config changes, | |
| # with a prefix fallback for warm restores. | |
| key: ${{ runner.os }}-sonar-${{ hashFiles('**/pom.xml') }} | |
| restore-keys: ${{ runner.os }}-sonar- | |
| - name: Cache Maven packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.m2 | |
| key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} | |
| restore-keys: ${{ runner.os }}-m2 | |
| - name: Build with Maven | |
| run: mvn -B install -Pmetrics --file pom.xml | |
| - name: Verify committed generated example builders | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| # Regenerate the example builders from a clean slate into their tracked | |
| # directory. Deleting first means a *missing* builder (generator | |
| # regression) shows up as a git deletion, stale output as a | |
| # modification, and a brand-new builder as an untracked file — so any | |
| # drift fails the check. (Dependencies were installed by the build step | |
| # above, so -pl example is sufficient here.) | |
| rm -rf example/generated-example-builder | |
| mvn -B -q -DskipTests -pl example clean compile | |
| CHANGES="$(git status --porcelain -- example/generated-example-builder)" | |
| if [ -n "$CHANGES" ]; then | |
| echo "::error::Committed generated example builders are out of date or missing." | |
| echo "Run 'mvn -pl example clean compile' and commit example/generated-example-builder/." | |
| echo "$CHANGES" | |
| git --no-pager diff -- example/generated-example-builder | |
| exit 1 | |
| fi | |
| echo "Committed generated example builders are up to date." | |
| - name: Package Sonar analysis inputs (fork PRs) | |
| if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository | |
| env: | |
| # Pass PR metadata through the environment (never interpolate the | |
| # attacker-controlled head ref/sha directly into the shell script). | |
| PR_NUMBER: ${{ github.event.number }} | |
| PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} | |
| PR_BASE_REF: ${{ github.event.pull_request.base.ref }} | |
| run: | | |
| mkdir -p sonar-analysis-data | |
| cp -a core/target/classes sonar-analysis-data/core-classes 2>/dev/null || true | |
| cp -a processor/target/classes sonar-analysis-data/processor-classes 2>/dev/null || true | |
| cp -a processor/target/site/jacoco-aggregate/jacoco.xml sonar-analysis-data/jacoco-aggregate.xml 2>/dev/null || true | |
| cp -a processor/target/site/jacoco/jacoco.xml sonar-analysis-data/processor-jacoco.xml 2>/dev/null || true | |
| { | |
| printf 'pr_number=%s\n' "$PR_NUMBER" | |
| printf 'pr_head_sha=%s\n' "$PR_HEAD_SHA" | |
| printf 'pr_head_ref=%s\n' "$PR_HEAD_REF" | |
| printf 'pr_base_ref=%s\n' "$PR_BASE_REF" | |
| } > sonar-analysis-data/pr-event.env | |
| - name: Upload Sonar analysis inputs (fork PRs) | |
| if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: sonar-analysis-inputs | |
| path: sonar-analysis-data/ | |
| if-no-files-found: warn | |
| - name: SonarCloud Analysis | |
| # Skip when SONAR_TOKEN is unavailable (fork PRs) and for any bot-authored | |
| # PR (Dependabot, Renovate, ...). The bot check uses the PR author's | |
| # account type rather than a hard-coded login, and is not defeated by a | |
| # maintainer re-run (which would otherwise make the withheld token appear). | |
| if: env.SONAR_TOKEN != '' && github.event.pull_request.user.type != 'Bot' | |
| run: mvn -B org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --file pom.xml | |
| - name: Upload JaCoCo HTML report (processor) | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: jacoco-report-html-processor | |
| path: processor/target/site/jacoco/ | |
| if-no-files-found: warn | |
| - name: Upload JaCoCo XML report (processor) | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: jacoco-report-xml-processor | |
| path: processor/target/site/jacoco/jacoco.xml | |
| if-no-files-found: warn | |
| # For PRs from forks, secrets are withheld so the direct Codecov steps | |
| # below are skipped. Instead publish the coverage data (plus the PR | |
| # identity) as an artifact; the privileged fork-coverage.yml workflow | |
| # (triggered on workflow_run, in the base-repo context) consumes it and | |
| # uploads to Codecov without ever executing fork code. | |
| - name: Assemble Codecov payload (fork PRs) | |
| if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository | |
| env: | |
| # Pass PR metadata through the environment (never interpolate the | |
| # attacker-controlled head ref/sha directly into the shell script). | |
| PR_NUMBER: ${{ github.event.number }} | |
| PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} | |
| run: | | |
| mkdir -p codecov-payload/surefire codecov-payload/failsafe | |
| cp -f processor/target/site/jacoco/jacoco.xml codecov-payload/ 2>/dev/null || true | |
| cp -f processor/target/site/jacoco-aggregate/jacoco.xml codecov-payload/jacoco-aggregate.xml 2>/dev/null || true | |
| cp -f processor/target/surefire-reports/*.xml codecov-payload/surefire/ 2>/dev/null || true | |
| cp -f processor/target/failsafe-reports/*.xml codecov-payload/failsafe/ 2>/dev/null || true | |
| { | |
| printf 'pr_number=%s\n' "$PR_NUMBER" | |
| printf 'pr_head_sha=%s\n' "$PR_HEAD_SHA" | |
| printf 'pr_head_ref=%s\n' "$PR_HEAD_REF" | |
| } > codecov-payload/pr-event.env | |
| - name: Upload Codecov payload artifact (fork PRs) | |
| if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: codecov-payload | |
| path: codecov-payload/ | |
| if-no-files-found: warn | |
| - name: Upload test results to Codecov (processor) | |
| # Skip when CODECOV_TOKEN is unavailable (fork PRs) and for any bot-authored PR. | |
| if: always() && env.CODECOV_TOKEN != '' && github.event.pull_request.user.type != 'Bot' | |
| uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1.2.1 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: | | |
| processor/target/surefire-reports/*.xml | |
| processor/target/failsafe-reports/*.xml | |
| fail_ci_if_error: true | |
| verbose: false | |
| - name: Upload coverage to Codecov (processor + core via aggregate) | |
| # Skip when CODECOV_TOKEN is unavailable (fork PRs) and for any bot-authored PR. | |
| if: always() && env.CODECOV_TOKEN != '' && github.event.pull_request.user.type != 'Bot' | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| fail_ci_if_error: true | |
| files: | | |
| processor/target/site/jacoco/jacoco.xml | |
| processor/target/site/jacoco-aggregate/jacoco.xml | |
| flags: processor | |
| name: codecov-upload | |
| verbose: false | |
| token: ${{ secrets.CODECOV_TOKEN }} |