name: Reusable - Common

on:
  workflow_call:
    inputs:
      cache-read-only:
        type: boolean
        required: false
      no-build-cache:
        type: boolean
        required: false
      skip-openj9-tests:
        type: boolean
        required: false
      skip-windows-smoke-tests:
        type: boolean
        required: false
    secrets:
      GRADLE_ENTERPRISE_ACCESS_KEY:
        required: false

permissions:
  contents: read

jobs:
  spotless:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Free disk space
        run: .github/scripts/gha-free-disk-space.sh

      - name: Set up JDK for running Gradle
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          distribution: temurin
          java-version: 21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2
        with:
          cache-read-only: ${{ inputs.cache-read-only }}
          # gradle enterprise is used for the build cache
          gradle-home-cache-excludes: caches/build-cache-1

      - name: Spotless
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        run: ./gradlew spotlessCheck ${{ inputs.no-build-cache && '--no-build-cache' || '' }}

  gradle-wrapper-validation:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - uses: gradle/actions/wrapper-validation@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2

  license-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Free disk space
        run: .github/scripts/gha-free-disk-space.sh

      - name: Set up JDK for running Gradle
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          distribution: temurin
          java-version: 21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2
        with:
          cache-read-only: ${{ inputs.cache-read-only }}
          # gradle enterprise is used for the build cache
          gradle-home-cache-excludes: caches/build-cache-1

      - name: Generate license report
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        # currently ignoring inputs.no-build-cache and always running with --no-build-cache
        # see https://github.com/jk1/Gradle-License-Report/issues/231
        run: ./gradlew generateLicenseReport --no-build-cache

      - name: Check licenses
        run: |
          # add any untracked folders that may have been added by generateLicenseReport
          git add licenses
          # there's always going to one line difference due to the timestamp included in the report
          if [[ $(git diff --cached --shortstat licenses) == " 1 file changed, 1 insertion(+), 1 deletion(-)" ]]
          then
            echo "Licenses are up-to-date."
          else
            echo "Licenses are not up-to-date, please run './gradlew generateLicenseReport' locally and commit."
            echo
            echo "$(git diff --cached --stat licenses)"
            echo
            echo "$(git diff --cached licenses)"
            exit 1
          fi

  # this is needed because we don't auto-update dependencies in instrumentation/**
  # and so we want to enforce that all "real" dependencies are dependency managed
  extra-dependency-management-enforcement:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Dependency check
        run: |
          set +e
          grep '^  implementation(".*:.*:[0-9].*")\|^  api(".*:.*:[0-9].*")' \
               --include=\*.kts \
               -r instrumentation \
            | grep -v testing/build.gradle.kts \
            | grep -v com.azure:azure-core-tracing-opentelemetry \
            | grep -v com.couchbase.client:tracing-opentelemetry \
            > dependencies.txt

          if [ -s dependencies.txt ]; then
            echo unmanaged dependencies found
            echo
            cat dependencies.txt
            exit 1
          fi

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Free disk space
        run: .github/scripts/gha-free-disk-space.sh

      - name: Set up JDK for running Gradle
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          distribution: temurin
          java-version: 21

      - name: Increase gradle daemon heap size
        run: |
          sed -i "s/org.gradle.jvmargs=/org.gradle.jvmargs=-Xmx3g /" gradle.properties

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2
        with:
          cache-read-only: ${{ inputs.cache-read-only }}
          # gradle enterprise is used for the build cache
          gradle-home-cache-excludes: caches/build-cache-1

      - name: Build
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        # javadoc task fails sporadically fetching https://docs.oracle.com/javase/8/docs/api/
        run: ./gradlew check -x javadoc -x spotlessCheck -PskipTests=true ${{ inputs.no-build-cache && '--no-build-cache' || '' }}

      - name: Check for jApiCmp diffs
        run: |
          # need to "git add" in case any generated files did not already exist
          git add docs/apidiffs
          if git diff --cached --quiet
          then
            echo "No diff detected."
          else
            echo "Diff detected - did you run './gradlew jApiCmp'?"
            echo $(git diff --cached --name-only)
            echo $(git diff --cached)
            exit 1
          fi

      - name: Upload agent jar
        uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        with:
          name: opentelemetry-javaagent
          path: javaagent/build/libs/opentelemetry-javaagent-*-SNAPSHOT.jar
          if-no-files-found: ignore

  test:
    name: test${{ matrix.test-partition }} (${{ matrix.test-java-version }}, ${{ matrix.vm }})
    runs-on: ubuntu-latest
    strategy:
      matrix:
        test-java-version:
          - 8
          - 11
          - 17
          - 21
          - 22
        vm:
          - hotspot
          - openj9
        test-partition:
          - 0
          - 1
          - 2
          - 3
        exclude:
          - vm: ${{ inputs.skip-openj9-tests && 'openj9' || '' }}
          - test-java-version: 22
            vm: openj9
      fail-fast: false
    steps:
      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Free disk space
        run: .github/scripts/gha-free-disk-space.sh

      - id: setup-test-java
        name: Set up JDK ${{ matrix.test-java-version }}-${{ matrix.vm }} for running tests
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          # using zulu because new releases get published quickly
          distribution: ${{ matrix.vm == 'hotspot' && 'zulu' || 'adopt-openj9'}}
          java-version: ${{ matrix.test-java-version }}

      - name: Set up JDK for running Gradle
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          distribution: temurin
          java-version: 21

      # vaadin 14 tests fail with node 18
      - name: Set up Node
        uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
        with:
          node-version: 16

      # vaadin tests use pnpm
      - name: Cache pnpm modules
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: ~/.pnpm-store
          key: ${{ runner.os }}-test-cache-pnpm-modules

      - name: Start deadlock detector
        run: .github/scripts/deadlock-detector.sh

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2
        with:
          # only push cache for one matrix option since github action cache space is limited
          cache-read-only: ${{ inputs.cache-read-only || matrix.test-java-version != 11 || matrix.vm != 'hotspot' }}
          # gradle enterprise is used for the build cache
          gradle-home-cache-excludes: caches/build-cache-1

      - name: List tests
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        # "check" is needed to activate all tests for listing purposes
        # listTestsInPartition writes test tasks that apply to the given partition to a file named
        # "test-tasks.txt" and then disables all tasks (including tests) after it runs
        run: >
          ./gradlew
          check -x spotlessCheck
          listTestsInPartition
          -PtestPartition=${{ matrix.test-partition }}

      - name: Set test tasks
        run: |
          echo "test-tasks=$(cat test-tasks.txt | xargs echo | sed 's/\n/ /g')" >> $GITHUB_ENV

      - name: Test
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        # spotless is checked separately since it's a common source of failure
        run: >
          ./gradlew
          ${{ env.test-tasks }}
          -PtestJavaVersion=${{ matrix.test-java-version }}
          -PtestJavaVM=${{ matrix.vm }}
          -Porg.gradle.java.installations.paths=${{ steps.setup-test-java.outputs.path }}
          -Porg.gradle.java.installations.auto-download=false
          ${{ inputs.no-build-cache && ' --no-build-cache' || '' }}

      - name: Build scan
        if: ${{ !cancelled() && hashFiles('build-scan.txt') != '' }}
        run: cat build-scan.txt

      - name: Upload deadlock detector artifacts if any
        if: failure()
        uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        with:
          name: deadlock-detector-test-${{ matrix.test-java-version }}-${{ matrix.vm }}-${{ matrix.test-partition }}
          path: /tmp/deadlock-detector-*
          if-no-files-found: ignore

      - name: Upload jvm crash dump files if any
        if: failure()
        uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        with:
          name: javacore-test-${{ matrix.test-java-version }}-${{ matrix.test-partition }}
          path: |
            **/hs_err_pid*.log
            **/javacore.*.txt
            **/Snap.*.trc
            **/core.*.dmp
            **/jitdump.*.dmp
          if-no-files-found: ignore

  smoke-test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os:
          - windows-latest
          - ubuntu-latest
        smoke-test-suite:
          - jetty
          - liberty
          - payara
          - tomcat
          - tomee
          - websphere
          - wildfly
          - other
        exclude:
          - os: ${{ inputs.skip-windows-smoke-tests && 'windows-latest' || '' }}
          - os: windows-latest
            smoke-test-suite: websphere
      fail-fast: false
    steps:
      - name: Support long paths
        run: git config --system core.longpaths true
        if: matrix.os == 'windows-latest'

      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Free disk space
        run: .github/scripts/gha-free-disk-space.sh

      - name: Set up JDK for running Gradle
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          distribution: temurin
          java-version: 21

      - name: Set up Gradle cache
        uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2
        with:
          # only push cache for one matrix option per OS since github action cache space is limited
          cache-read-only: ${{ inputs.cache-read-only || matrix.smoke-test-suite != 'tomcat' }}
          # gradle enterprise is used for the build cache
          gradle-home-cache-excludes: caches/build-cache-1

      - name: Build
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        # running suite "none" compiles everything needed by smoke tests without executing any tests
        run: ./gradlew :smoke-tests:test -PsmokeTestSuite=none --no-daemon ${{ inputs.no-build-cache && ' --no-build-cache' || '' }}

      - name: Test
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        run: ./gradlew :smoke-tests:test -PsmokeTestSuite=${{ matrix.smoke-test-suite }}${{ inputs.no-build-cache && ' --no-build-cache' || '' }}

      - name: Upload jvm crash dump files if any
        if: failure()
        uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        with:
          name: javacore-smoke-test-${{ matrix.smoke-test-suite }}-${{ matrix.os }}
          # we expect crash dumps either in root director or in smoke-tests
          # not using **/ here because actions/upload-artifact fails with long paths https://github.com/actions/upload-artifact/issues/309
          path: |
            hs_err_pid*.log
            smoke-tests/hs_err_pid*.log
            javacore.*.txt
            smoke-tests/javacore.*.txt
            Snap.*.trc
            smoke-tests/Snap.*.trc
            core.*.dmp
            smoke-tests/core.*.dmp
            jitdump.*.dmp
            smoke-tests/jitdump.*.dmp
          if-no-files-found: ignore

  gradle-plugins:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Free disk space
        run: .github/scripts/gha-free-disk-space.sh

      - name: Set up JDK for running Gradle
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          distribution: temurin
          java-version: 21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2
        with:
          cache-read-only: ${{ inputs.cache-read-only }}

      - name: Build
        run: ./gradlew build ${{ inputs.no-build-cache && '--no-build-cache' || '' }}
        working-directory: gradle-plugins

  examples:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Free disk space
        run: .github/scripts/gha-free-disk-space.sh

      - name: Set up JDK for running Gradle
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          distribution: temurin
          java-version: 21

      - name: Set up Gradle cache
        uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2
        with:
          cache-read-only: ${{ inputs.cache-read-only }}

      - name: Local publish of artifacts
        # javadoc task fails sporadically fetching https://docs.oracle.com/javase/8/docs/api/
        run: ./gradlew publishToMavenLocal -x javadoc

      - name: Local publish of gradle plugins
        # javadoc task fails sporadically fetching https://docs.oracle.com/javase/8/docs/api/
        run: ./gradlew publishToMavenLocal -x javadoc
        working-directory: gradle-plugins

      - name: Build distro
        run: ./gradlew build --init-script ../../.github/scripts/local.init.gradle.kts${{ inputs.no-build-cache && ' --no-build-cache' || '' }}
        working-directory: examples/distro

      - name: Build extension
        run: ./gradlew build --init-script ../../.github/scripts/local.init.gradle.kts${{ inputs.no-build-cache && ' --no-build-cache' || '' }}
        working-directory: examples/extension

      - name: Run muzzle check against extension
        run: ./gradlew muzzle --init-script ../../.github/scripts/local.init.gradle.kts
        working-directory: examples/extension
