# Every workflow that includes this must also include the following to make sure that it
# is triggered when a new JDK is added to the matrix:
#on:
#  push:
#    paths:
#      - ".github/workflows/reusable-smoke-test-images.yml"

name: PR build fake backend images for smoke tests

on:
  workflow_call:
    inputs:
      project:
        type: string
        required: true
      publish:
        type: boolean
        required: false
      cache-read-only:
        type: boolean
        required: false
      skip-java-8:
        type: boolean
        required: false
      skip-java-17:
        type: boolean
        required: false
      skip-java-21:
        type: boolean
        required: false

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      packages: write # for publishing docker image to github packages
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

      - name: Login to GitHub package registry
        if: inputs.publish
        uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Set tag
        run: echo "TAG=$(date '+%Y%m%d').$GITHUB_RUN_ID" >> $GITHUB_ENV

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

      - name: Build Java 8 Docker image
        if: "!inputs.skip-java-8"
        run: ./gradlew ${{ inputs.project }}:${{ inputs.publish && 'jib' || 'jibDockerBuild' }} -Ptag=${{ env.TAG }} -PtargetJDK=8 -Djib.httpTimeout=120000 -Djib.console=plain

      - name: Build Java 11 Docker image
        run: ./gradlew ${{ inputs.project }}:${{ inputs.publish && 'jib' || 'jibDockerBuild' }} -Ptag=${{ env.TAG }} -PtargetJDK=11 -Djib.httpTimeout=120000 -Djib.console=plain

      - name: Build Java 17 Docker image
        if: "!inputs.skip-java-17"
        run: ./gradlew ${{ inputs.project }}:${{ inputs.publish && 'jib' || 'jibDockerBuild' }} -Ptag=${{ env.TAG }} -PtargetJDK=17 -Djib.httpTimeout=120000 -Djib.console=plain

      - name: Build Java 21 Docker image
        if: "!inputs.skip-java-21"
        run: ./gradlew ${{ inputs.project }}:${{ inputs.publish && 'jib' || 'jibDockerBuild' }} -Ptag=${{ env.TAG }} -PtargetJDK=21 -Djib.httpTimeout=120000 -Djib.console=plain


Reusable - Muzzle

name: Reusable - Muzzle

on:
  workflow_call:
    inputs:
      cache-read-only:
        type: boolean
        required: false

permissions:
  contents: read

jobs:
  muzzle:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        task:
          - ":instrumentation:muzzle1"
          - ":instrumentation:muzzle2"
          - ":instrumentation:muzzle3"
          - ":instrumentation:muzzle4"
      fail-fast: false
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

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

      - name: Run muzzle
        run: ./gradlew ${{ matrix.task }}


Reusable - Test latest deps

name: Reusable - Test latest deps

on:
  workflow_call:
    inputs:
      cache-read-only:
        type: boolean
        required: false
      no-build-cache:
        type: boolean
        required: false
    secrets:
      GRADLE_ENTERPRISE_ACCESS_KEY:
        required: false

permissions:
  contents: read

jobs:
  test-latest-deps:
    name: testLatestDeps${{ matrix.test-partition }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        test-partition:
          - 0
          - 1
          - 2
          - 3
      fail-fast: false
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

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

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

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

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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: List tests
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        run: >
          ./gradlew
          check -x spotlessCheck
          listTestsInPartition
          -PtestPartition=${{ matrix.test-partition }}
          -PtestLatestDeps=true

      - 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 }}
        run: >
          ./gradlew
          ${{ env.test-tasks }}
          -PtestLatestDeps=true
          ${{ 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-latest-${{ 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-latest-${{ 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


Build pull request

name: Build pull request

on:
  pull_request:

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  common:
    uses: ./.github/workflows/build-common.yml
    with:
      # it's rare for only the openj9 tests or the windows smoke tests to break
      skip-openj9-tests: ${{ !contains(github.event.pull_request.labels.*.name, 'test openj9') }}
      skip-windows-smoke-tests: ${{ !contains(github.event.pull_request.labels.*.name, 'test windows') }}
      cache-read-only: true

  test-latest-deps:
    uses: ./.github/workflows/reusable-test-latest-deps.yml
    with:
      cache-read-only: true

  test-indy:
    uses: ./.github/workflows/reusable-test-indy.yml
    with:
      cache-read-only: true

  test-native:
    uses: ./.github/workflows/reusable-native-tests.yml
    with:
      skip-native-tests: ${{ !contains(github.event.pull_request.labels.*.name, 'test native') }}

  muzzle:
    uses: ./.github/workflows/reusable-muzzle.yml
    with:
      cache-read-only: true

  shell-script-check:
    uses: ./.github/workflows/reusable-shell-script-check.yml

  # this is not a required check to avoid blocking pull requests if external links break
  markdown-link-check:
    # release branches are excluded because the README.md javaagent download link has to be updated
    # on release branches before the release download has been published
    if: "!startsWith(github.ref_name, 'release/') && !startsWith(github.base_ref, 'release/')"
    uses: ./.github/workflows/reusable-markdown-link-check.yml

  markdown-lint-check:
    uses: ./.github/workflows/reusable-markdown-lint-check.yml

  misspell-check:
    uses: ./.github/workflows/reusable-misspell-check.yml

  required-status-check:
    # test-latest-deps is not included in the required status checks
    # because any time a new library version is released to maven central
    # it can fail due to test code incompatibility with the new library version,
    # or due to slight changes in emitted telemetry
    # (muzzle can also fail when a new library version is released to maven central
    # but that happens much less often)
    #
    # only the "common" checks are required for release branch PRs in order to avoid any unnecessary
    # release branch maintenance (especially for patches)
    needs:
      - common
      - muzzle
      - shell-script-check
      - markdown-lint-check
      - misspell-check
    runs-on: ubuntu-latest
    if: always()
    steps:
      - if: |
          needs.common.result != 'success' ||
          (
            !startsWith(github.base_ref, 'release/') &&
            (
              needs.muzzle.result != 'success' ||
              needs.shell-script-check.result != 'success' ||
              needs.markdown-lint-check.result != 'success' ||
              needs.misspell-check.result != 'success'
            )
          )
        run: exit 1 # fail


Build (daily --no-build-cache)

name: Build (daily --no-build-cache)

on:
  schedule:
    # daily at 4:48 UTC
    - cron: "48 4 * * *"
  workflow_dispatch:

jobs:
  common:
    uses: ./.github/workflows/build-common.yml
    with:
      no-build-cache: true
    secrets:
      GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}

  test-latest-deps:
    uses: ./.github/workflows/reusable-test-latest-deps.yml
    with:
      no-build-cache: true
    secrets:
      GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}

  # muzzle is not included here because it doesn't use gradle cache anyway and so is already covered
  # by the normal daily build

  # markdown-link-check and misspell-check are not included here because they don't use gradle cache
  # anyway and so are already covered by the normal daily build

  workflow-notification:
    needs:
      - common
      - test-latest-deps
    if: always()
    uses: ./.github/workflows/reusable-workflow-notification.yml
    with:
      success: >-
        ${{
          needs.common.result == 'success' &&
          needs.test-latest-deps.result == 'success'
        }}


Build (daily)

name: Build (daily)

on:
  schedule:
    # daily at 3:24 UTC
    - cron: "24 3 * * *"
  workflow_dispatch:

jobs:
  common:
    uses: ./.github/workflows/build-common.yml
    secrets:
      GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}

  test-latest-deps:
    uses: ./.github/workflows/reusable-test-latest-deps.yml
    secrets:
      GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}

  muzzle:
    uses: ./.github/workflows/reusable-muzzle.yml

  shell-script-check:
    uses: ./.github/workflows/reusable-shell-script-check.yml

  markdown-link-check:
    uses: ./.github/workflows/reusable-markdown-link-check.yml

  markdown-lint-check:
    uses: ./.github/workflows/reusable-markdown-lint-check.yml

  misspell-check:
    uses: ./.github/workflows/reusable-misspell-check.yml

  workflow-notification:
    needs:
      - common
      - test-latest-deps
      - muzzle
      - markdown-link-check
      - misspell-check
    if: always()
    uses: ./.github/workflows/reusable-workflow-notification.yml
    with:
      success: >-
        ${{
          needs.common.result == 'success' &&
          needs.test-latest-deps.result == 'success' &&
          needs.muzzle.result == 'success' &&
          needs.markdown-link-check.result == 'success' &&
          needs.misspell-check.result == 'success'
        }}


CodeQL (daily)

name: CodeQL (daily)

on:
  schedule:
    # daily at 1:30 UTC
    - cron: "30 1 * * *"
  workflow_dispatch:

permissions:
  contents: read

jobs:
  analyze:
    permissions:
      actions: read  # for github/codeql-action/init to get workflow details
      security-events: write  # for github/codeql-action/analyze to upload SARIF results
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

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

      - name: Set up Java 17
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          distribution: temurin
          java-version-file: .java-version

      - name: Initialize CodeQL
        uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
        with:
          languages: java
          # using "latest" helps to keep up with the latest Kotlin support
          # see https://github.com/github/codeql-action/issues/1555#issuecomment-1452228433
          tools: latest

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.2

      - name: Build
        # skipping build cache is needed so that all modules will be analyzed
        run: ./gradlew assemble -x javadoc --no-build-cache --no-daemon

      - name: Perform CodeQL analysis
        uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10

  workflow-notification:
    needs:
      - analyze
    if: always()
    uses: ./.github/workflows/reusable-workflow-notification.yml
    with:
      success: ${{ needs.analyze.result == 'success' }}


Overhead benchmark (daily)

name: Overhead benchmark (daily)
on:
  schedule:
    # daily at 5:00 UTC
    - cron: "0 5 * * *"
  workflow_dispatch:

jobs:
  run-overhead-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          ref: gh-pages
          path: gh-pages

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

      - name: Copy results from gh-pages branch
        run: |
          rsync -avv gh-pages/benchmark-overhead/results/ benchmark-overhead/results/

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.2

      - name: Run tests
        working-directory: benchmark-overhead
        run: ./gradlew test

      - name: Inspect the results dir
        working-directory: benchmark-overhead
        run: ls -lR results

      - name: Copy results back to gh-pages branch
        run: rsync -avv benchmark-overhead/results/ gh-pages/benchmark-overhead/results/ && rm -rf benchmark-overhead/results

      - name: Commit updated results
        uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
        with:
          add: "benchmark-overhead/results"
          cwd: "./gh-pages"
          branch: "gh-pages"
          message: "update test result data"
          author_name: opentelemetrybot
          author_email: 107717825+opentelemetrybot@users.noreply.github.com
          committer_name: opentelemetrybot
          committer_email: 107717825+opentelemetrybot@users.noreply.github.com

  workflow-notification:
    needs:
      - run-overhead-tests
    if: always()
    uses: ./.github/workflows/reusable-workflow-notification.yml
    with:
      success: ${{ needs.run-overhead-tests.result == 'success' }}


Publish PetClinic benchmark image

name: Publish PetClinic benchmark image
on:
  push:
    paths:
      - "benchmark-overhead/Dockerfile-petclinic-base"
    branches:
      - main
  workflow_dispatch:

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - name: Login to GitHub container registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Create timestamp for docker image tag
        run: echo "TS=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV

      - name: Push to GitHub packages
        uses: docker/build-push-action@v6
        with:
          push: true
          file: benchmark-overhead/Dockerfile-petclinic-base
          tags: ghcr.io/open-telemetry/opentelemetry-java-instrumentation/petclinic-rest-base:${{ env.TS }}


Reusable - Markdown link check

name: Reusable - Markdown link check

on:
  workflow_call:

permissions:
  contents: read

jobs:
  markdown-link-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Install markdown-link-check
        # https://github.com/tcort/markdown-link-check/issues/297
        run: npm install -g markdown-link-check@3.11.2

      - name: Run markdown-link-check
        run: |
          find . -type f \
                 -name '*.md' \
                 -not -path './CHANGELOG.md' \
                 -not -path './licenses/*' \
                 -not -path '*/build/*' \
               | xargs .github/scripts/markdown-link-check-with-retry.sh


Reusable - Misspell check

name: Reusable - Misspell check

on:
  workflow_call:

permissions:
  contents: read

jobs:
  misspell-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Install misspell
        run: |
          curl -L -o install-misspell.sh \
               https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh
          sh ./install-misspell.sh

      - name: Run misspell
        run: |
          find . -type f \
                 -not -path './licenses/*' \
               | xargs bin/misspell -error


Backport

name: Backport
on:
  workflow_dispatch:
    inputs:
      number:
        description: "The pull request # to backport"
        required: true

permissions:
  contents: read

jobs:
  backport:
    permissions:
      contents: write  # for Git to git push
    runs-on: ubuntu-latest
    steps:
      - run: |
          if [[ ! $GITHUB_REF_NAME =~ ^release/v[0-9]+\.[0-9]+\.x$ ]]; then
            echo this workflow should only be run against release branches
            exit 1
          fi

      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          # history is needed to run git cherry-pick below
          fetch-depth: 0

      - name: Use CLA approved github bot
        run: .github/scripts/use-cla-approved-github-bot.sh

      - name: Create pull request
        env:
          NUMBER: ${{ github.event.inputs.number }}
          # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
          GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
        run: |
          commit=$(gh pr view $NUMBER --json mergeCommit --jq .mergeCommit.oid)
          title=$(gh pr view $NUMBER --json title --jq .title)

          branch="opentelemetrybot/backport-${NUMBER}-to-${GITHUB_REF_NAME//\//-}"

          git checkout -b $branch
          git cherry-pick $commit
          git push --set-upstream origin $branch
          gh pr create --title "[$GITHUB_REF_NAME] $title" \
                       --body "Clean cherry-pick of #$NUMBER to the \`$GITHUB_REF_NAME\` branch." \
                       --base $GITHUB_REF_NAME


Assign reviewers

# assigns reviewers to pull requests in a similar way as CODEOWNERS, but doesn't require reviewers
# to have write access to the repository
# see .github/component_owners.yaml for the list of components and their owners
name: Assign reviewers

on:
  # pull_request_target is needed instead of just pull_request
  # because repository write permission is needed to assign reviewers
  pull_request_target:

jobs:
  assign-reviewers:
    runs-on: ubuntu-latest
    steps:
      - uses: trask/component-owners@main
        with:
          # this repository is using this action to request doc review
          assign-owners: false


OWASP dependency check (daily)

# the benefit of this over dependabot is that this also analyzes transitive dependencies
# while dependabot (at least currently) only analyzes top-level dependencies
name: OWASP dependency check (daily)

on:
  schedule:
    # daily at 1:30 UTC
    - cron: "30 1 * * *"
  workflow_dispatch:

jobs:
  analyze:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

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

      - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.2

      - run: ./gradlew :javaagent:dependencyCheckAnalyze
        env:
          NVD_API_KEY: ${{ secrets.NVD_API_KEY }}

      - name: Upload report
        if: always()
        uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        with:
          path: javaagent/build/reports

  workflow-notification:
    needs:
      - analyze
    if: always()
    uses: ./.github/workflows/reusable-workflow-notification.yml
    with:
      success: ${{ needs.analyze.result == 'success' }}


Reusable - Common

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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - uses: gradle/actions/wrapper-validation@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.2

  license-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

      - 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@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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 spdxSbom -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.jar
          path: javaagent/build/libs/opentelemetry-javaagent-*-SNAPSHOT.jar
          if-no-files-found: ignore

      - name: Collect SBOMs
        run: |
          mkdir sboms
          cp javaagent/build/spdx/*.spdx.json sboms

      - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        name: Upload SBOMs
        with:
          name: opentelemetry-java-instrumentation-SBOM.zip
          path: "sboms/*.json"

  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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

      # 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@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

      - name: Set up Gradle cache
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

      - name: Set up Gradle cache
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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


Reusable - Shell script check

name: Reusable - Shell script check

on:
  workflow_call:

permissions:
  contents: read

jobs:
  shell-script-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Install shell check
        run: wget -qO- "https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz" | tar -xJv

      - name: Run shellcheck
        run: find -name '*.sh' | xargs shellcheck-stable/shellcheck --format=gcc


Reusable - Markdown lint check

name: Reusable - Markdown lint check

on:
  workflow_call:

permissions:
  contents: read

jobs:
  markdown-lint-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Install mardkdownlint
        run: npm install -g markdownlint-cli

      - name: Run markdownlint
        run: |
          markdownlint -c .markdownlint.yml -p .gitignore **/*.md -i licenses/licenses.md


name: Issue management - remove labels as needed

on:
  issue_comment:
    types: [created]

jobs:
  issue_comment:
    if: >
      contains(github.event.issue.labels.*.name, 'needs author feedback') &&
      github.event.comment.user.login == github.event.issue.user.login
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Remove labels
        env:
          ISSUE_NUMBER: ${{ github.event.issue.number }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh issue edit --remove-label "needs author feedback" $ISSUE_NUMBER
          gh issue edit --remove-label "stale" $ISSUE_NUMBER


Issue management - run stale action

name: Issue management - run stale action

on:
  schedule:
    # hourly at minute 23
    - cron: "23 * * * *"

permissions:
  contents: read

jobs:
  stale:
    permissions:
      issues: write  # for actions/stale to close stale issues
      pull-requests: write  # for actions/stale to close stale PRs
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          days-before-stale: 7
          days-before-close: 7
          only-labels: "needs author feedback"
          stale-issue-label: stale
          stale-issue-message: >
            This has been automatically marked as stale because it has been marked
            as needing author feedback and has not had any activity for 7 days.
            It will be closed automatically if there is no response from the author
            within 7 additional days from this comment.
          stale-pr-label: stale
          stale-pr-message: >
            This has been automatically marked as stale because it has been marked
            as needing author feedback and has not had any activity for 7 days.
            It will be closed automatically if there is no response from the author
            within 7 additional days from this comment.


Auto-update OpenTelemetry SDK

name: Auto-update OpenTelemetry SDK

on:
  schedule:
    # hourly at minute 46
    - cron: "46 * * * *"
  workflow_dispatch:

jobs:
  check-versions:
    runs-on: ubuntu-latest
    outputs:
      current-version: ${{ steps.check-versions.outputs.current-version }}
      latest-version: ${{ steps.check-versions.outputs.latest-version }}
      already-opened: ${{ steps.check-versions.outputs.already-opened }}
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - id: check-versions
        name: Check versions
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          current_version=$(grep -Po "val otelSdkVersion = \"\K[0-9]+.[0-9]+.[0-9]+" \
                                dependencyManagement/build.gradle.kts)
          latest_version=$(gh release view \
                               --repo open-telemetry/opentelemetry-java \
                               --json tagName \
                               --jq .tagName \
                             | sed 's/^v//')

          matches=$(gh pr list \
                        --author opentelemetrybot \
                        --state open \
                        --search "in:title \"Update the OpenTelemetry SDK version to $latest_version\"")
          if [ ! -z "$matches" ]
          then
            already_opened=true
          fi

          echo "current-version=$current_version" >> $GITHUB_OUTPUT
          echo "latest-version=$latest_version" >> $GITHUB_OUTPUT
          echo "already-opened=$already_opened" >> $GITHUB_OUTPUT

  update-otel-sdk:
    permissions:
      contents: write  # for Git to git push
    runs-on: ubuntu-latest
    if: |
      needs.check-versions.outputs.current-version != needs.check-versions.outputs.latest-version &&
      needs.check-versions.outputs.already-opened != 'true'
    needs:
      - check-versions
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Update version
        env:
          VERSION: ${{ needs.check-versions.outputs.latest-version }}
        run: ./.github/scripts/update-sdk-version.sh $VERSION

      - name: Use CLA approved github bot
        run: .github/scripts/use-cla-approved-github-bot.sh

      - 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-file: .java-version

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.2

      - name: Update license report
        run: ./gradlew generateLicenseReport

      - name: Undo license report clean
        if: failure()
        run: git checkout -- licenses

      - name: Create pull request against main
        if: success() || failure()
        env:
          VERSION: ${{ needs.check-versions.outputs.latest-version }}
          # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
          GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
        run: |
          message="Update the OpenTelemetry SDK version to $VERSION"
          body="Update the OpenTelemetry SDK version to \`$VERSION\`."
          branch="opentelemetrybot/update-opentelemetry-sdk-to-${VERSION}"

          git checkout -b $branch
          git add -u
          git add licenses
          git commit -m "$message"
          git push --set-upstream origin $branch
          gh pr create --title "$message" \
                       --body "$body" \
                       --base main


name: PR build Security Manager test app images for smoke tests

on:
  pull_request:
    paths:
      - "smoke-tests/images/security-manager/**"
      - ".github/workflows/pr-smoke-test-security-manager-images.yml"
      - ".github/workflows/reusable-smoke-test-images.yml"
    branches:
      - main

jobs:
  build:
    uses: ./.github/workflows/reusable-smoke-test-images.yml
    with:
      project: ":smoke-tests:images:security-manager"
      cache-read-only: true


name: Publish Security Manager test app images for smoke tests

on:
  push:
    paths:
      - "smoke-tests/images/security-manager/**"
      - ".github/workflows/publish-smoke-test-security-manager-images.yml"
      - ".github/workflows/reusable-smoke-test-images.yml"
    branches:
      - main

jobs:
  publish:
    uses: ./.github/workflows/reusable-smoke-test-images.yml
    with:
      project: ":smoke-tests:images:security-manager"
      publish: true

  workflow-notification:
    needs:
      - publish
    if: always()
    uses: ./.github/workflows/reusable-workflow-notification.yml
    with:
      success: ${{ needs.publish.result == 'success' }}


Reusable - Workflow notification

# this is useful because notifications for scheduled workflows are only sent to the user who
# initially created the given workflow
name: Reusable - Workflow notification

on:
  workflow_call:
    inputs:
      success:
        type: boolean
        required: true

jobs:
  workflow-notification:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Open issue or add comment if issue already open
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # TODO (trask) search doesn't support exact phrases, so it's possible that this could grab the wrong issue
          number=$(gh issue list --search "in:title Workflow failed: $GITHUB_WORKFLOW" --limit 1 --json number -q .[].number)

          echo $number
          echo ${{ inputs.success }}

          if [[ $number ]]; then
            if [[ "${{ inputs.success }}" == "true" ]]; then
              gh issue close $number
            else
              gh issue comment $number \
                               --body "See [$GITHUB_WORKFLOW #$GITHUB_RUN_NUMBER](https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID)."
            fi
          elif [[ "${{ inputs.success }}" == "false" ]]; then
            gh issue create --title "Workflow failed: $GITHUB_WORKFLOW (#$GITHUB_RUN_NUMBER)" \
                            --body "See [$GITHUB_WORKFLOW #$GITHUB_RUN_NUMBER](https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID)."
          fi


Daily GraalVM native tests

name: Daily GraalVM native tests

on:
  schedule:
    # daily at 4:00 UTC
    - cron: "0 4 * * *"
  workflow_dispatch:

jobs:
  graalvm-native-tests:
    uses: ./.github/workflows/reusable-native-tests.yml
    with:
      test-latest-deps: true

  workflow-notification:
    needs:
      - graalvm-native-tests
    if: always()
    uses: ./.github/workflows/reusable-workflow-notification.yml
    with:
      success: ${{ needs.graalvm-native-tests.result == 'success' }}


Update cloudfoundry release index

# This action updates the CloudFoundry java-buildpack release index after each release.
# See https://github.com/cloudfoundry/java-buildpack/blob/main/docs/extending-repositories.md
# Prerequisite: the repo must have a branch named "cloudfoundry".

name: Update cloudfoundry release index
on:
  schedule:
    - cron: '25 4 * * *' # Daily at 4:25 AM UTC
  workflow_dispatch:

permissions:
  contents: write
  pull-requests: write

jobs:

  update-cloudfoundry-index-yml:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Use CLA approved github bot
        run: .github/scripts/use-cla-approved-github-bot.sh

      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          ref: 'cloudfoundry'

      - name: create working branch
        run: git checkout -b opentelemetrybot/cloudfoundry-${{ github.run_number }}-${{ github.run_attempt }}

      - run: sudo apt-get install jq python3-pip
      - run: pip install yq

      - name: update index.yml
        run: |
          wget https://repo1.maven.org/maven2/io/opentelemetry/javaagent/opentelemetry-javaagent/maven-metadata.xml
          xq -r .metadata.versioning.versions.version[] maven-metadata.xml | sed -E 's/(.*)/\1: https:\/\/repo1.maven.org\/maven2\/io\/opentelemetry\/javaagent\/opentelemetry-javaagent\/\1\/opentelemetry-javaagent-\1.jar/' > index.yml

      - name: display changes
        run: git diff

      - name: create pr with repo changes
        run: |
          git add index.yml
          if git diff-index --quiet --cached HEAD ; then
            echo "index.yml already current"
            exit 0
          fi
          git commit -m "Updated index.yml"
          git push --set-upstream origin opentelemetrybot/cloudfoundry-${{ github.run_number }}-${{ github.run_attempt }}
          gh pr create --base cloudfoundry \
            --head opentelemetrybot/cloudfoundry-${{ github.run_number }}-${{ github.run_attempt }} \
            --title 'Release updates for Cloudfoundry Repo' \
            --body '[Created by Github action]'
        env:
          # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
          GITHUB_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}


Reusable - Test latest deps

name: Reusable - Test latest deps

on:
  workflow_call:
    inputs:
      cache-read-only:
        type: boolean
        required: false
      no-build-cache:
        type: boolean
        required: false
    secrets:
      GRADLE_ENTERPRISE_ACCESS_KEY:
        required: false

permissions:
  contents: read

jobs:
  test-indy:
    name: testIndy${{ matrix.test-partition }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        test-partition:
          - 0
          - 1
          - 2
          - 3
      fail-fast: false
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - 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-file: .java-version

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

      # 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-latest-cache-pnpm-modules

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.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: List tests
        env:
          GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
        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 }}
        run: >
          ./gradlew
          ${{ env.test-tasks }}
          -PtestIndy=true
          ${{ inputs.no-build-cache && ' --no-build-cache' || '' }}

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


Scorecard supply-chain security

name: Scorecard supply-chain security

on:
  # For Branch-Protection check. Only the default branch is supported. See
  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
  branch_protection_rule:
  # To guarantee Maintained check is occasionally updated. See
  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
  schedule:
    - cron: '43 6 * * 5'
  push:
    branches: [ "main" ]

# Declare default permissions as read only.
permissions: read-all

jobs:
  analysis:
    name: Scorecard analysis
    runs-on: ubuntu-latest
    permissions:
      # Needed to upload the results to code-scanning dashboard.
      security-events: write
      # Needed to publish results and get a badge (see publish_results below).
      id-token: write
      # Uncomment the permissions below if installing in a private repository.
      # contents: read
      # actions: read

    steps:
      - name: "Checkout code"
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          persist-credentials: false

      - name: "Run analysis"
        uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
        with:
          results_file: results.sarif
          results_format: sarif
          # (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
          # - you want to enable the Branch-Protection check on a *public* repository, or
          # - you are installing Scorecard on a *private* repository
          # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
          # repo_token: ${{ secrets.SCORECARD_TOKEN }}

          # Public repositories:
          #   - Publish results to OpenSSF REST API for easy access by consumers
          #   - Allows the repository to include the Scorecard badge.
          #   - See https://github.com/ossf/scorecard-action#publishing-results.
          # For private repositories:
          #   - `publish_results` will always be set to `false`, regardless
          #     of the value entered here.
          publish_results: true

      # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
      # format to the repository Actions tab.
      - name: "Upload artifact"
        uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        with:
          name: SARIF file
          path: results.sarif
          retention-days: 5

      # Upload the results to GitHub's code scanning dashboard.
      - name: "Upload to code-scanning"
        uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
        with:
          sarif_file: results.sarif


Reusable - Native tests

name: Reusable - Native tests

on:
  workflow_call:
    inputs:
      skip-native-tests:
        type: boolean
        required: false
      test-latest-deps:
        type: boolean
        required: false

jobs:
  graalvm-native-tests:
    if: "!inputs.skip-native-tests"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - id: read-java
        run: echo "version=$(cat .java-version)" >> "$GITHUB_OUTPUT"
      - uses: graalvm/setup-graalvm@2911b2304bee2c2f59b9a67bf45f025a6b6de4b1 # v1.2.2.1
        with:
          version: "latest"
          java-version: "${{ steps.read-java.outputs.version }}"
          components: "native-image"
      - name: Running test
        env:
          DOCKER_COMPOSE_TEST: "true"
        run: |
          echo "GRAALVM_HOME: $GRAALVM_HOME"
          echo "JAVA_HOME: $JAVA_HOME"
          java --version
          native-image --version
          # Testcontainers does not work in some cases with GraalVM native images,
          # therefore we're starting a Kafka container manually for the tests
          docker compose -f .github/graal-native-docker-compose.yaml up -d
          # don't wait for startup - gradle compile takes long enough
          ./gradlew ${{ inputs.test-latest-deps && '-PtestLatestDeps=true' || '' }} nativeTest
          docker compose -f .github/graal-native-docker-compose.yaml down # is this needed?


Labeler

name: Labeler
on: [pull_request_target]

jobs:
  label:

    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
    - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
      with:
        repo-token: "${{ secrets.GITHUB_TOKEN }}"


PR build early jdk8 images for smoke tests


Publish early jdk8 images for smoke tests


build

name: "build"

on:
  push:
    branches: "**"
    tags-ignore: ["**"]
  pull_request:

jobs:
  call-build:
    uses: "KyoriPowered/.github/.github/workflows/shared-ci.yaml@trunk"
    secrets: "inherit"


rebuild docs on release

name: "rebuild docs on release"

on:
  release:
    types: ["created", "edited", "deleted"]
  workflow_dispatch:

jobs:
  call-build:
    uses: "KyoriPowered/.github/.github/workflows/shared-rebuild-docs.yaml@trunk"
    secrets: "inherit"


name: Run CheckStyle
on: pull_request, merge_group

jobs:
  checkstyle_job:
    runs-on: ubuntu-latest
    name: Checkstyle job
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Run check style
        uses: nikitasavinov/checkstyle-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          checkstyle_config: '.github/checkstyle-rules.xml'
          reporter: 'github-pr-review'
#          filter_mode: 'file' # https://github.com/nikitasavinov/checkstyle-action
          fail_on_error: true
          level: 'error'
          tool_name: 'CheckStyle'


Unit test(Ubuntu)

name: Unit test(Ubuntu)
on:
  push:
    branches:
      - master
  pull_request:
  merge_group:
jobs:
  test:
    runs-on: ubuntu-latest
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK
        uses: actions/setup-java@v3
        with:
          distribution: oracle
          java-version: 17

      - name: Run unit tests
        run: sh ./build.sh

      - name: Upload Test Reports Folder
        uses: actions/upload-artifact@v2
        if: ${{ always() }} # IMPORTANT: Upload reports regardless of status
        with:
          name: ut-reports
          path: app/build/reports/tests

      - name: Upload coverage reports to Codecov
        run: |
          curl -Os https://uploader.codecov.io/latest/linux/codecov
          chmod +x codecov
          ./codecov


Unit test(Windows)

name: Unit test(Windows)
on:
  push:
    branches:
      - master
  pull_request:
  merge_group:
jobs:
  test:
    runs-on: windows-latest
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK
        uses: actions/setup-java@v3
        with:
          distribution: oracle
          java-version: 17

      - name: Run unit tests
        run: sh ./build.sh

      - name: Upload Test Reports Folder
        uses: actions/upload-artifact@v2
        if: ${{ always() }} # IMPORTANT: Upload reports regardless of status
        with:
          name: ut-reports
          path: app/build/reports/tests

      - name: Upload coverage reports to Codecov
        run: |
          curl -Os https://uploader.codecov.io/latest/windows/codecov
          chmod +x codecov
          ./codecov


Unit test(MacOS)

name: Unit test(MacOS)
on:
  push:
    branches:
      - master
  pull_request:
  merge_group:
jobs:
  test:
    runs-on: macos-latest
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK
        uses: actions/setup-java@v3
        with:
          distribution: oracle
          java-version: 17

      - name: Run unit tests
        run: sh ./build.sh

      - name: Upload Test Reports Folder
        uses: actions/upload-artifact@v2
        if: ${{ always() }} # IMPORTANT: Upload reports regardless of status
        with:
          name: ut-reports
          path: app/build/reports/tests

      - name: Upload coverage reports to Codecov
        run: |
          curl -Os https://uploader.codecov.io/latest/macos/codecov
          chmod +x codecov
          ./codecov


E2e Test

name: E2e Test
on:
  push:
    branches:
      - master
  pull_request:
  merge_group:
jobs:
  test:
    runs-on: self-hosted
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    timeout-minutes: 40
    strategy:
      matrix:
        api-level: [28]
        target: [default]
    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK
        uses: actions/setup-java@v3
        with:
          distribution: oracle
          java-version: 17
          architecture: x64

      - uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: 'npm'
      - run: npm install ganache --global

      - name: Run tests
        run: |
          rm -rf ./output
          mkdir ./output
          adb shell settings put secure long_press_timeout 1500
          adb shell settings put global window_animation_scale 0.0
          adb shell settings put global transition_animation_scale 0.0
          adb shell settings put global animator_duration_scale 0.0
          adb shell settings put secure show_ime_with_hard_keyboard 0
          ganache --chain.chainId 2 -h 0.0.0.0 -p 8555 -m "horse light surface bamboo combine item lumber tunnel choose acid mail feature" &
          adb logcat >> output/emulator.log &
          ./gradlew :app:uninstallAll :app:connectedNoAnalyticsDebugAndroidTest -x lint -PdisablePreDex
          kill %1
          kill %2

      - name: Collect tests results
        if: ${{ failure() }}
        uses: actions/upload-artifact@v1
        with:
          name: e2e-tests-results
          path: output/

  cleanup:
    if: ${{ always() }}
    needs: test
    runs-on: self-hosted
    steps:
      - run: ./gradlew :app:uninstallAll


name: Comments Android lint warnings on pull request
on: pull_request
jobs:
  lint:
    name: Comments lint result on PR
    runs-on: macos-latest
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - name: set up JDK
        uses: actions/setup-java@v3
        with:
          distribution: oracle
          java-version: 17
          cache: gradle
      - name: Run detekt
        run: ./gradlew :app:detekt
        continue-on-error: true
      - name: Run Android Lint
        run: ./gradlew :app:lintAnalyticsDebug
      - name: Run Android Lint Reporter to report Lint and Detekt result to PR
        env:
          PR_NUMBER: ${{ github.event.number }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          ./gradlew report --no-configuration-cache -PgithubPullRequestId=$PR_NUMBER -PgithubToken=$GITHUB_TOKEN


Android lint

name: Android lint
on:
  push:
    branches:
      - master
  pull_request:
  merge_group:
jobs:
  lint:
    name: Comments lint result on Master
    runs-on: macos-latest
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - name: set up JDK
        uses: actions/setup-java@v3
        with:
          distribution: oracle
          java-version: 17
          cache: gradle
      - name: Run detekt
        run: ./gradlew :app:detekt
        continue-on-error: true
      - name: Run Android Lint
        run: ./gradlew :app:lintAnalyticsDebug


Pull Request Stats

name: Pull Request Stats
on:
  pull_request:
    types: [opened]
jobs:
  stats:
    runs-on: ubuntu-latest
    steps:
      - name: Run pull request stats
        uses: flowwer-dev/pull-request-stats@master
        with:
          charts: true
          sort-by: 'COMMENTS'


Build

name: Build
on:
  push:
    branches:
      - v5
jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4 #https://github.com/actions/checkout/releases
        with:
          fetch-depth: 0  # Shallow clones should be disabled for a better relevancy of analysis
      - name: Set up JDK 21
        uses: actions/setup-java@v4 #https://github.com/actions/setup-java/releases
        with:
          distribution: 'temurin'
          java-version: 21
      - name: Cache SonarCloud packages
        uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
        with:
          path: ~/.sonar/cache
          key: ${{ runner.os }}-sonar
          restore-keys: ${{ runner.os }}-sonar
      - name: Cache Gradle
        uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}"
          restore-keys: |
            ${{ runner.os }}-gradle-
      - name: Build and analyze
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # Needed to get PR information, if any
        run: ./gradlew clean build
      - name: Upload a Build Artifact
        uses: actions/upload-artifact@v3.1.2 #https://github.com/actions/upload-artifact/releases
        with:
          name: Click here to download
          path: jar/build/libs/TAB-**.jar


Continuous Integration Build

---
name: Continuous Integration Build

on:
    push:
        branches:
            - main
            - 3.x
        paths-ignore:
            - '.github/**'

jobs:
    build:
        runs-on: ubuntu-latest
        continue-on-error: ${{ matrix.java.continue-on-error == true }}
        strategy:
            matrix:
                java: [
                    {
                        'name': '',
                        'version': '11',
                        'build_opts': '-Drevapi.skip=true'
                    },
                    {
                        'name': '',
                        'version': '17',
                    },
                    {
                        'name': '',
                        'version': '21',
                    },
                    {
                        'version': '21',
                        'build_opts': '-Pslow-flaky-tests -Drevapi.skip=true -Dformat.skip=true',
                        'name': 'Slow and Flaky tests',
                        'continue-on-error': true
                    }
                ]
        name: Build with Java ${{ matrix.java.version }} ${{ matrix.java.name }}
        steps:
            -   uses: actions/checkout@v4
            -   uses: actions/setup-java@v4
                with:
                    java-version: ${{ matrix.java.version }}
                    distribution: temurin
                    cache: maven
            -   name: Build with Maven
                env:
                    MAVEN_OPTS: ${{ matrix.java.opts }}
                run: |
                    mvn -s .build/ci-maven-settings.xml -Dmaven.resolver.transport=wagon -B \
                      clean install -Dtest-containers=true ${{ matrix.java.build_opts }}

    quality:
        needs: build
        runs-on: ubuntu-latest
        steps:
            -   uses: actions/checkout@v4
            -   uses: actions/setup-java@v4
                with:
                    java-version: 11
                    distribution: temurin
                    cache: maven
            -   name: Coverage and Sonar
                env:
                    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
                    SONAR_TOKEN: ${{ secrets.SONAR_LOGIN }}
                run: |
                    mvn -s .build/ci-maven-settings.xml -B \
                        clean install sonar:sonar -Pcoverage \
                        -Dmaven.resolver.transport=wagon \
                        -Drevapi.skip=true \
                        -Dsonar.projectKey=smallrye_smallrye-reactive-messaging \
                        -Dsonar.projectName="SmallRye Reactive Messaging" \
                        -Dsonar.organization=smallrye \
                        -Dsonar.host.url=https://sonarcloud.io \
                        -Dsonar.login=$SONAR_LOGIN \
                        --fail-at-end
            -   name: Codecov
                uses: codecov/codecov-action@v4.5.0
                if: false


Continuous Integration Build – Podman

---
name: Continuous Integration Build – Podman

on:
    push:
        branches:
            - main
        paths-ignore:
            - '.github/**'

jobs:
    build:
        runs-on: ubuntu-latest
        continue-on-error: ${{ matrix.java.continue-on-error == true }}
        strategy:
            matrix:
                java: [
                    {
                        'name': '',
                        'version': '11',
                        'build_opts': '-Drevapi.skip=true'
                    },
                    {
                        'name': '',
                        'version': '17',
                    },
                    {
                        'name': '',
                        'version': '21',
                    },
                    {
                        'version': '11',
                        'build_opts': '-Pslow-flaky-tests -Drevapi.skip=true',
                        'name': 'Slow and Flaky tests',
                        'continue-on-error': true
                    }
                ]
        name: Build with Java ${{ matrix.java.version }} ${{ matrix.java.name }}
        steps:
            -   name: Setup docker host
                run: echo "DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock" >> "$GITHUB_ENV"
            -   name: Update podman
                run: |
                    sudo apt-get -y purge podman
                    sudo mkdir -p /etc/apt/keyrings
                    curl -fsSL https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_$(lsb_release -rs)/Release.key | gpg --dearmor | sudo tee /etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg > /dev/null
                    echo \
                      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg] \
                      https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_$(lsb_release -rs)/ /" \
                      | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list > /dev/null
                    sudo apt-get update -qq
                    sudo apt-get -qq -y install podman
                    sudo bash -c "echo -e '[engine]\nservice_timeout=0' >> /etc/containers/containers.conf"
            # Runs a single command using the runners shell
            -   name: Check podman
                run: docker version
            -   name: Set up testcontainers for podman
                run: |
                    echo ryuk.container.privileged=true > ~/.testcontainers.properties
            -   uses: actions/checkout@v4
            -   uses: actions/setup-java@v4
                with:
                    java-version: ${{ matrix.java.version }}
                    distribution: temurin
                    cache: maven
            -   name: Build with Maven
                env:
                    MAVEN_OPTS: ${{ matrix.java.opts }}
                run: |
                    mvn -s .build/ci-maven-settings.xml -Dmaven.resolver.transport=wagon -B \
                      clean install -Dtest-containers=true ${{ matrix.java.build_opts }}


Pull Request Build

---
name: Pull Request Build

on:
    pull_request:
        branches:
            - main
            - 3.x
            - 3.13.x

jobs:
    build:
        runs-on: ubuntu-latest
        continue-on-error: ${{ matrix.java.continue-on-error == true }}
        strategy:
            matrix:
                java: [
                    {
                        'name': '',
                        'version': '11',
                        'build_opts': '-Drevapi.skip=true'
                    },
                    {
                        'name': '',
                        'version': '17',
                    },
                    {
                        'name': '',
                        'version': '21',
                    },
                    {
                        'version': '21',
                        'build_opts': '-Pslow-flaky-tests -Drevapi.skip=true -Dformat.skip=true',
                        'name': 'Slow and Flaky tests',
                        'continue-on-error': true
                    }
                ]
        name: Build with Java ${{ matrix.java.version }} ${{ matrix.java.name }}
        steps:
            -   uses: actions/checkout@v4
            -   uses: actions/setup-java@v4
                with:
                    java-version: ${{ matrix.java.version }}
                    distribution: temurin
                    cache: maven
            -   name: Build with Maven
                env:
                    MAVEN_OPTS: ${{ matrix.java.opts }}
                run: |
                    mvn -s .build/ci-maven-settings.xml -Dmaven.resolver.transport=wagon \
                       -B clean install -Pcoverage -Dtest-containers=true ${{ matrix.java.build_opts }}
            -   name: Codecov
                uses: codecov/codecov-action@v4.5.0
                if: false


Deploy Docs Smallrye Reactive Messaging

name: Deploy Docs Smallrye Reactive Messaging

on:
    workflow_dispatch:
        inputs:
            version:
                description: 'Release version'

jobs:
    deploy-docs:
        runs-on: ubuntu-latest
        env:
            GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
            RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
            RELEASE_VERSION: ${{ github.event.inputs.version }}

        steps:
            - name: Git checkout
              uses: actions/checkout@v4
              with:
                  fetch-depth: 0
                  token: ${{ secrets.RELEASE_TOKEN }}
            - name: Java setup
              uses: actions/setup-java@v4
              with:
                  java-version: '17'
                  distribution: 'temurin'
                  cache: maven
            - name: Install just
              uses: taiki-e/install-action@just
            - name: Setup Python
              uses: actions/setup-python@v5
              with:
                  python-version: 3.9
                  cache: 'pipenv'
                  cache-dependency-path: documentation/Pipfile.lock
            - name: Install pipenv
              run: pip install pipenv
            - name: Set Release Version
              run: |
                echo "RELEASE_VERSION=${RELEASE_VERSION:-"$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)"}" >> $GITHUB_ENV
            - name: Perform the deploy docs
              run: |
                just build-ci deploy-docs


Push a release to Maven Central

name: Push a release to Maven Central

on:
    push:
        tags:
            - '4.*'

jobs:
    deploy:
        runs-on: ubuntu-latest
        env:
            SECRET_FILES_PASSPHRASE: ${{ secrets.SECRET_FILES_PASSPHRASE }}
        steps:
            - name: Git checkout
              uses: actions/checkout@v4
            - name: Java setup
              uses: actions/setup-java@v4
              with:
                  java-version: '17'
                  distribution: 'temurin'
                  cache: maven
            - name: Install just
              uses: taiki-e/install-action@just
            - name: Deploy to Maven Central
              run: just deploy-to-maven-central


Release Smallrye Reactive Messaging

name: Release Smallrye Reactive Messaging

on:
    workflow_dispatch:
        inputs:
            previousVersion:
                description: 'Previous version'
                required: true
            version:
                description: 'Release version'
                required: true
            deployWebsite:
                description: 'Shall we deploy the website?'
                required: true
                default: 'true'
            clearRevAPI:
                description: 'Shall we clear RevAPI justifications?'
                required: true
                default: 'true'

jobs:
    release:
        runs-on: ubuntu-latest
        env:
            GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
            RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
            SECRET_FILES_PASSPHRASE: ${{ secrets.SECRET_FILES_PASSPHRASE }}
            RELEASE_VERSION: ${{ github.event.inputs.version }}
            DEPLOY_WEBSITE: ${{ github.event.inputs.deployWebsite }}
            CLEAR_REVAPI: ${{ github.event.inputs.clearRevAPI }}
            JRELEASER_TAG_NAME: ${{ github.event.inputs.version }}
            JRELEASER_PREVIOUS_TAG_NAME: ${{ github.event.inputs.previousVersion }}
            JRELEASER_GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}

        steps:
            - name: Git checkout
              uses: actions/checkout@v4
              with:
                  fetch-depth: 0
                  token: ${{ secrets.RELEASE_TOKEN }}
            - name: Java setup
              uses: actions/setup-java@v4
              with:
                  java-version: '17'
                  distribution: 'temurin'
                  cache: maven
            - name: Install just
              uses: taiki-e/install-action@just
            - name: Setup Python
              uses: actions/setup-python@v5
              with:
                  python-version: 3.9
                  cache: 'pipenv'
                  cache-dependency-path: documentation/Pipfile.lock
            - name: Install pipenv
              run: pip install pipenv
            - name: Perform the release steps
              run: |
                curl -s "https://get.sdkman.io?rcupdate=false" | bash
                source ~/.sdkman/bin/sdkman-init.sh && sdk install jbang
                just perform-release


Package

name: Package

on: workflow_dispatch

permissions:
  contents: read

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [windows-2022, ubuntu-20.04, macos-12]
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - name: Set up JDK 18.0.1
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '18.0.1'
      - name: Show Build Versions
        run: ./gradlew -v
      - name: Build with Gradle
        run: ./gradlew jpackage
      - name: Package zip distribution
        if: ${{ runner.os == 'Windows' || runner.os == 'macOS' }}
        run: ./gradlew packageZipDistribution
      - name: Package tar distribution
        if: ${{ runner.os == 'Linux' }}
        run: ./gradlew packageTarDistribution
      - name: Upload Artifacts
        uses: actions/upload-artifact@v4
        with:
          name: Sparrow Build - ${{ runner.os }}
          path: |
            build/jpackage/*
            !build/jpackage/Sparrow/
      - name: Headless build with Gradle
        if: ${{ runner.os == 'Linux' }}
        run: ./gradlew -Djava.awt.headless=true clean jpackage
      - name: Package headless tar distribution
        if: ${{ runner.os == 'Linux' }}
        run: ./gradlew -Djava.awt.headless=true packageTarDistribution
      - name: Rename Headless Artifacts
        if: ${{ runner.os == 'Linux' }}
        run: for f in build/jpackage/sparrow*; do mv -v "$f" "${f/sparrow/sparrow-server}"; done;
      - name: Upload Headless Artifact
        if: ${{ runner.os == 'Linux' }}
        uses: actions/upload-artifact@v4
        with:
          name: Sparrow Build - ${{ runner.os }} Headless
          path: |
            build/jpackage/*
            !build/jpackage/Sparrow/


Check Code Style

name: Check Code Style

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  check-code-style:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # brew install sbt; cd graphql-java-codegen-sbt-plugin; sbt fmt or sbt check
      - name: Check Scala Code Style
        working-directory: plugins/sbt/graphql-java-codegen-sbt-plugin
        run: sbt check

      - name: Check Code Style
        env:
          WORKDIR: ./
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CHECKSTYLE_CONFIG: config/checkstyle/graphql-codegen-check-style.xml
          REVIEWDOG_VERSION: v0.11.0
        run: |
          wget -O - -q https://github.com/checkstyle/checkstyle/releases/download/checkstyle-8.41/checkstyle-8.41-all.jar > /opt/checkstyle.jar
          wget -O - -q https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s -- -b /opt ${REVIEWDOG_VERSION}
          java -jar /opt/checkstyle.jar "${WORKDIR}" -c "${CHECKSTYLE_CONFIG}"  -f xml \
               | /opt/reviewdog -f=checkstyle \
                    -reporter="${INPUT_REPORTER:-github-pr-check}" \
                    -filter-mode="${INPUT_FILTER_MODE:-added}" \
                    -fail-on-error="${INPUT_FAIL_ON_ERROR:-false}"


Build

name: Build

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        jdk-version: [ 8, 11, 17 ]
    steps:
      - uses: actions/checkout@v4

      - name: Setup Java ${{ matrix.jdk-version }}
        uses: actions/setup-java@v4
        with:
          java-version: ${{ matrix.jdk-version }}
          distribution: 'adopt'

      - name: Gradle cache
        uses: actions/cache@v4
        with:
          path: ~/.gradle
          key: gradle

      - name: Maven cache
        uses: actions/cache@v4
        with:
          path: ~/.m2
          key: m2

      - name: Loading ivy cache
        uses: actions/cache@v4
        with:
          path: ~/.ivy2/cache
          key: ${{ runner.os }}-ivy-${{ hashFiles('**/*.sbt') }}
          restore-keys: |
            ${{ runner.os }}-ivy-

      - name: Build library
        run: ./gradlew build publishToMavenLocal publishAllPublicationsToIvyRepository --warning-mode all

      - name: Build maven plugin
        working-directory: plugins/maven/graphql-java-codegen-maven-plugin
        run: mvn install

      - name: Build maven example-server
        working-directory: plugins/maven/example-server
        run: mvn package

      - name: Build maven example-client
        working-directory: plugins/maven/example-client
        run: mvn package

      - name: Build gradle plugin
        run: ./gradlew -p plugins/gradle/graphql-java-codegen-gradle-plugin build publishToMavenLocal --warning-mode all

      - name: Build gradle example-server
        run: ./gradlew -p plugins/gradle/example-server test --warning-mode all

      - name: Build gradle example-client
        run: ./gradlew -p plugins/gradle/example-client test --warning-mode all

      - name: Build gradle example-client-kotlin
        run: ./gradlew -p plugins/gradle/example-client-kotlin build --warning-mode all

      - name: Build sbt plugin
        working-directory: plugins/sbt/graphql-java-codegen-sbt-plugin
        run: sbt compile publishLocal --debug

      - name: Build sbt test
        working-directory: plugins/sbt/graphql-java-codegen-sbt-plugin
        run: sbt scripted

  sonar:
    needs: build
    if: github.event_name != 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
         fetch-depth: 0
      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'adopt'

      - name: Gradle cache
        uses: actions/cache@v4
        with:
          path: ~/.gradle
          key: gradle

      - name: Maven cache
        uses: actions/cache@v4
        with:
          path: ~/.m2
          key: m2

      - name: Loading ivy cache
        uses: actions/cache@v4
        with:
          path: ~/.ivy2/cache
          key: ${{ runner.os }}-ivy-${{ hashFiles('**/*.sbt') }}
          restore-keys: |
            ${{ runner.os }}-ivy-

      - name: Generate code coverage report
        run: ./gradlew codeCoverageReport --stacktrace

      - name: Generate and publish Sonar report
        run: ./gradlew sonarqube -Dsonar.projectKey=kobylynskyi_graphql-java-codegen -Dsonar.organization=kobylynskyi -Dsonar.host.url=https://sonarcloud.io -Dsonar.token=${{ secrets.SONAR_TOKEN }} --stacktrace
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


Release

name: Release

on:
  workflow_dispatch:
    inputs:
      release_version:
        description: 'Release version'
        default: 'X.X.X'
        required: true
      release_branch:
        description: 'Release branch'
        default: 'main'
        required: true
      publish_library:
        description: 'Publish library'
        default: 'Y'
        required: true
      publish_gradle_plugin:
        description: 'Publish Gradle Plugin'
        default: 'Y'
        required: true
      publish_maven_plugin:
        description: 'Publish Maven Plugin'
        default: 'Y'
        required: true
      publish_sbt_plugin:
        description: 'Publish SBT Plugin'
        default: 'Y'
        required: true

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.release_branch }}

      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          java-version: 1.8
          distribution: 'adopt'

      - name: Gradle cache
        uses: actions/cache@v4
        with:
          path: ~/.gradle
          key: gradle

      - name: Maven cache
        uses: actions/cache@v4
        with:
          path: ~/.m2
          key: m2

      - name: Loading ivy cache
        uses: actions/cache@v4
        with:
          path: ~/.ivy2/cache
          key: ${{ runner.os }}-ivy-${{ hashFiles('**/*.sbt') }}
          restore-keys: |
            ${{ runner.os }}-ivy-

      - name: Set up GPG
        run: |
          echo ${{ github.workspace }}
          # gpg init
          mkdir ~/.gnupg && echo use-agent >> ~/.gnupg/gpg.conf
          echo pinentry-mode loopback >> ~/.gnupg/gpg.conf
          echo allow-loopback-pinentry >> ~/.gnupg/gpg-agent.conf
          echo RELOADAGENT | gpg-connect-agent
          echo ${SIGNING_KEY} | awk '{gsub(/\\n/,"\n")}1'| gpg --dearmor > ${{ github.workspace }}/secretKeyRingFile.gpg
          gpg --import  --pinentry-mode loopback --batch --passphrase '${SIGNING_PASSWORD}' ${{ github.workspace }}/secretKeyRingFile.gpg
          ls -al ${{ github.workspace }}
          ls -al ~/.gnupg/
        env:
          SIGNING_KEY: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
          SIGNING_PASSWORD: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}

      - name: Configure Git
        run: |
          git config --global user.name 'Bogdan Kobylynskyi'
          git config --global user.email 'kobylynskyi@users.noreply.github.com'

      - name: Update version of Maven plugin sub-project
        working-directory: plugins/maven/graphql-java-codegen-maven-plugin
        run: mvn versions:set -DnewVersion="${{ github.event.inputs.release_version }}" -DgenerateBackupPoms=false

      - name: Update version of Maven example client sub-project
        working-directory: plugins/maven/example-client
        run: mvn versions:set -DnewVersion="${{ github.event.inputs.release_version }}" -DgenerateBackupPoms=false

      - name: Update version of Maven example server sub-project
        working-directory: plugins/maven/example-server
        run: mvn versions:set -DnewVersion="${{ github.event.inputs.release_version }}" -DgenerateBackupPoms=false

      - name: Update versions of all Gradle/SBT sub-projects
        run: scripts/update-release-version-in-build-files.sh ${{ github.event.inputs.release_version }}

      - name: Update versions in all README files
        run: scripts/update-release-version-in-readme.sh ${{ github.event.inputs.release_version }}

      #
      # VERSIONS UPDATED
      # NOW WE ARE READY FOR THE FINAL BUILD
      #

      - name: Build library
        run: ./gradlew build publishToMavenLocal publishAllPublicationsToIvyRepository --warning-mode all

      - name: Build maven plugin
        if: github.event.inputs.publish_maven_plugin == 'Y'
        working-directory: plugins/maven/graphql-java-codegen-maven-plugin
        run: mvn install

      - name: Build maven example-server
        if: github.event.inputs.publish_maven_plugin == 'Y'
        working-directory: plugins/maven/example-server
        run: mvn package

      - name: Build maven example-client
        if: github.event.inputs.publish_maven_plugin == 'Y'
        working-directory: plugins/maven/example-client
        run: mvn package

      - name: Build gradle plugin
        run: ./gradlew -p plugins/gradle/graphql-java-codegen-gradle-plugin build publishToMavenLocal --warning-mode all

      - name: Build gradle example-server
        if: github.event.inputs.publish_gradle_plugin == 'Y'
        run: ./gradlew -p plugins/gradle/example-server test --warning-mode all

      - name: Build gradle example-client
        if: github.event.inputs.publish_gradle_plugin == 'Y'
        run: ./gradlew -p plugins/gradle/example-client test --warning-mode all

      - name: Build gradle example-client-kotlin
        if: github.event.inputs.publish_gradle_plugin == 'Y'
        run: ./gradlew -p plugins/gradle/example-client-kotlin build --warning-mode all

      - name: Build sbt plugin
        if: github.event.inputs.publish_sbt_plugin == 'Y'
        working-directory: plugins/sbt/graphql-java-codegen-sbt-plugin
        run: sbt compile publishLocal --debug

      - name: Build sbt test
        if: github.event.inputs.publish_sbt_plugin == 'Y'
        working-directory: plugins/sbt/graphql-java-codegen-sbt-plugin
        run: sbt scripted

      #
      # BUILD OF RELEASE VERSION COMPLETED
      # SO WE CAN COMMIT THEM
      #

      - name: Update version of Maven plugin to SNAPSHOT (required by publish-plugin)
        if: github.event.inputs.publish_maven_plugin == 'Y'
        working-directory: plugins/maven/graphql-java-codegen-maven-plugin
        run: mvn versions:set -DnewVersion="${{ github.event.inputs.release_version }}-SNAPSHOT" -DgenerateBackupPoms=false

      - name: Commit release version
        run: git commit -am "Bump version to ${{ github.event.inputs.release_version }}"

      #
      # VERSIONS ARE IN THE RELEASE STATE AND READY TO PUBLISH
      #

      - name: Release library
        if: github.event.inputs.publish_library == 'Y'
        run: |
          ./gradlew publish \
                -Dorg.gradle.internal.publish.checksums.insecure=true \
                -PsonatypeUsername=${{ secrets.OSSRH_USERNAME }} \
                -PsonatypePassword=${{ secrets.OSSRH_PASSWORD }} \
                -Psigning.keyId=${{ secrets.OSSRH_GPG_SECRET_KEY_ID }} \
                -Psigning.password=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} \
                -Psigning.secretKeyRingFile=${{ github.workspace }}/secretKeyRingFile.gpg

      - name: Release Gradle plugin
        if: github.event.inputs.publish_gradle_plugin == 'Y'
        run: |
          ./gradlew -p plugins/gradle/graphql-java-codegen-gradle-plugin publishPlugins \
              -Dorg.gradle.internal.publish.checksums.insecure=true \
              -Pgradle.publish.key=${{ secrets.GRADLE_PUBLISH_KEY}} \
              -Pgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }}

      - name: Release Maven plugin
        if: github.event.inputs.publish_maven_plugin == 'Y'
        working-directory: plugins/maven/graphql-java-codegen-maven-plugin
        run: |
          mvn \
            --settings .maven.xml \
            --no-transfer-progress \
            --batch-mode \
            -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} \
            release:clean release:prepare release:perform
        env:
          GPG_EXECUTABLE: gpg
          GPG_SECRET_KEYS: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
          GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
          SONATYPE_USER: ${{ secrets.OSSRH_USERNAME }}
          SONATYPE_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}

      - name: Release SBT plugin
        if: github.event.inputs.publish_sbt_plugin == 'Y'
        working-directory: plugins/sbt/graphql-java-codegen-sbt-plugin
        run: sbt ci-release
        env:
          PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
          PGP_SECRET: ${{ secrets.PGP_SECRET }}
          SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
          SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}

      #
      # PUBLISH OF RELEASE VERSION COMPLETED
      # NOW PUSHING THE RELEASE VERSION BACK TO THE REPOSITORY
      #

      - name: Push release version
        run: |
          git push
          git push --tags


Update Version

name: Update Version

on:
  workflow_dispatch:
    inputs:
      new_version:
        description: 'New version'
        required: true

jobs:
  update-version:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Update version of Maven plugin sub-project
        working-directory: plugins/maven/graphql-java-codegen-maven-plugin
        run: mvn versions:set -DnewVersion="${{ github.event.inputs.new_version }}" -DgenerateBackupPoms=false

      - name: Update version of Maven example client sub-project
        working-directory: plugins/maven/example-client
        run: mvn versions:set -DnewVersion="${{ github.event.inputs.new_version }}" -DgenerateBackupPoms=false

      - name: Update version of Maven example server sub-project
        working-directory: plugins/maven/example-server
        run: mvn versions:set -DnewVersion="${{ github.event.inputs.new_version }}" -DgenerateBackupPoms=false

      - name: Update versions of all Gradle/SBT sub-projects
        run: scripts/update-release-version-in-build-files.sh ${{ github.event.inputs.new_version }}

      - name: Commit and push a new version
        run: |
          git config --global user.name 'Bogdan Kobylynskyi'
          git config --global user.email 'kobylynskyi@users.noreply.github.com'
          git commit -am "Bump version to ${{ github.event.inputs.new_version }}"
          git push
          git push --tags


Backport

#
# 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: Backport
on:
  pull_request:
    types:
      - closed
      - labeled

jobs:
  backport:
    runs-on: ubuntu-latest
    name: Backport
    steps:
      - name: "Checkout camel-kafka-connector"
        uses: actions/checkout@v4.1.6
        with:
          persist-credentials: false
          submodules: recursive
      - name: Backport
        uses: ./.github/actions/backport
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}