diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000000..a2c772f1116 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,99 @@ +version: 2.1 +orbs: + mvn: lsk/mvn@1.3 + +anchors: + run-on-semver-tags: &run-on-semver-tags + filters: + tags: + only: /^[0-9]+[.][0-9]+[.][0-9]+(-.*)*$/ + +jobs: + build: + executor: mvn/java-11 + resource_class: xlarge + steps: + - checkout + - restore_cache: + keys: + - gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "settings.gradle.kts" }}-{{ .Branch }} + - gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "settings.gradle.kts" }} + - gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }} + - run: + name: Build + command: ./gradlew clean assemble --no-daemon --parallel + - save_cache: + paths: + - ~/.gradle/caches + - ~/.gradle/wrapper + key: gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "settings.gradle.kts" }}-{{ .Branch }}-{{ .Revision }} + - persist_to_workspace: + root: . + paths: + - "*/build" + - "*/*/build" + - "*/*/*/build" + - "*/*/*/*/build" + + test: + executor: mvn/java-11 + resource_class: xlarge + steps: + - checkout + - attach_workspace: + at: . + - restore_cache: + keys: + - gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "settings.gradle.kts" }}-{{ .Branch }} + - gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "settings.gradle.kts" }} + - run: + name: Test + command: ./gradlew test --no-daemon --parallel + - run: + name: Save test results + command: | + mkdir -p ~/test-results/junit/ + find . -type f -name "TEST-*.xml" -path "*/build/test-results/*" -exec cp {} ~/test-results/junit/ \; + when: always + - store_test_results: + path: ~/test-results + - store_artifacts: + path: ~/test-results/junit + + publish: + executor: mvn/java-11 + resource_class: xlarge + steps: + - checkout + - attach_workspace: + at: . + - restore_cache: + keys: + - gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "settings.gradle.kts" }}-{{ .Branch }} + - gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "settings.gradle.kts" }} + - run: + name: Publish to GitHub Packages + command: ./gradlew publish --no-daemon + +workflows: + version: 2 + workflow: + jobs: + - build: + context: global + <<: *run-on-semver-tags + - test: + context: global + requires: + - build + <<: *run-on-semver-tags + - publish: + context: global + requires: + - test + <<: *run-on-semver-tags + filters: + tags: + only: /^[0-9]+[.][0-9]+[.][0-9]+(-.*)*$/ + branches: + ignore: /.*/ diff --git a/.github/workflows/README.md b/.github/workflows/README.md deleted file mode 100644 index 936eabafe63..00000000000 --- a/.github/workflows/README.md +++ /dev/null @@ -1,200 +0,0 @@ -# GitHub Actions Documentation - -This lists and describes the repository GitHub actions, how to maintain and test them. - -## Release Management - -### add-milestone-to-pull-requests [🔗](add-milestone-to-pull-requests.yaml) - -_Trigger:_ When a PR targeting `master` or a patch release (`release/vM.N.x`) branch is closed. - -_Action:_ Attach the corresponding milestone to the closed pull request (if not set). - -_Recovery:_ Attach the milestone by hand to the PR. - -### add-release-to-cloudfoundry [🔗](add-release-to-cloudfoundry.yaml) - -_Trigger:_ When a release is published. - -_Action:_ Append the new release to the Cloud Foundry repository. - -_Recovery:_ Manually edit and push the `index.yml` file from [the cloudfoundry branch](https://github.com/DataDog/dd-trace-java/tree/cloudfoundry). - -### check-pull-requests [🔗](check-pull-requests.yaml) - -_Trigger:_ When creating or updating a pull request. - -_Action:_ Check the pull request complies with [the contribution guidelines](https://github.com/DataDog/dd-trace-java/blob/master/CONTRIBUTING.md). - -_Recovery:_ Manually verify the guideline compliance. - -### check-pull-request-labels [🔗](check-pull-request-labels.yaml) - -_Trigger:_ When creating or updating a pull request, or when new commits are pushed to it. - -_Actions:_ - -* Detect AI-generated pull requests then apply the `tag: ai generated` label. -* Check the pull request did not introduce unexpected labels. - -_Recovery:_ Update the pull request or add a comment to trigger the action again. - -### enforce-datadog-merge-queue [🔗](enforce-datadog-merge-queue.yaml) - -_Trigger:_ When creating or updating a pull request, or when a pull request is added to GitHub merge queue. - -_Actions:_ - -* Pass the `Merge queue check` status check on pull requests so they remain in a mergeable state, -* When a pull request is enqueued in GitHub merge queue, post a `/merge` comment to trigger the Datadog merge queue, -* Fail the `Merge queue check` status check on merge groups to prevent GitHub from merging directly. - -_Recovery:_ The workflow is expected to fail to block GitHub merge queue. -This redirects GitHub's "Merge when ready" button to the Datadog merge queue system. - -### create-release-branch [🔗](create-release-branch.yaml) - -_Trigger:_ When a git tag matching the pattern "vM.N.0" is pushed (e.g. for a minor release). - -_Action:_ Create a release branch that corresponds to the pushed tag (e.g. "release/vM.N.x"). Then open a PR against the release branch that pins system tests. - -_Recovery:_ Manually create the release branch from the "vM.N.0" git tag, and pin system tests to this branch by running the `./tooling/update_system_test_reference.sh` script. - -### draft-release-notes-on-tag [🔗](draft-release-notes-on-tag.yaml) - -_Trigger:_ When creating a tag, or manually (providing a tag) - -_Actions:_ - -* Fetch merged pull requests from the related tag milestone, -* Generate changelog draft, -* Create a new draft release for given tag with the generated changelog. - -_Recovery:_ Manually trigger the action again on the relevant tag. - -### increment-milestone-on-tag [🔗](increment-milestone-on-tag.yaml) - -_Trigger:_ When creating a minor or major version tag. - -_Actions:_ - -* Close the milestone related to the tag, -* Create a new milestone by incrementing minor version. - -_Recovery:_ Manually [close the related milestone and create a new one](https://github.com/DataDog/dd-trace-java/milestones). - -_Notes:_ This action will not apply to release candidate versions using `-RC` tags. - -### prune-old-pull-requests [🔗](prune-old-pull-requests.yaml) - -_Trigger:_ Every month or manually. - -_Action:_ Mark as stale and comment on pull requests with no update during the last quarter. -Close them if no following update within a week. - -_Recovery:_ Manually trigger the action again. - -### update-download-releases [🔗](update-download-releases.yaml) - -_Trigger:_ When a release is published. - -_Action:_ Update the _download releases_ with the latest release artifact. - -_Recovery:_ Download artifacts and upload them manually to the related _download release_. - -_Notes:_ _Download releases_ are special GitHub releases with fixed URL and tags, but rolling artifacts to provided stable download links (ex [latest](https://github.com/DataDog/dd-trace-java/releases/tag/download-latest) and [latest-v1](https://github.com/DataDog/dd-trace-java/releases/tag/download-latest-v1)). - -### update-issues-on-release [🔗](update-issues-on-release.yaml) - -_Trigger:_ When a release is published. Releases of type `prereleased` should skip this. - -_Action:_ - -* Find all issues related to the release by checking the related milestone, -* Add a comment to let know the issue was addressed by the newly published release, -* Close all those issues. - -_Recovery:_ Check at the milestone for the related issues and update them manually. - -### enforce-groovy-migration [🔗](enforce-groovy-migration.yaml) - -_Trigger:_ When creating or updating a pull request targeting `master`, or when labels are updated. - -_Actions:_ - -* Fail the PR if it introduces any new `.groovy` file, including added, copied, or renamed files whose previous name was not already `.groovy`. - -_Recovery:_ Re-write the new Groovy files in Java / JUnit. To override this check entirely, add the `tag: override-groovy-enforcement` label to the PR. Remove the label to re-enable enforcement. - -_Notes:_ The override label skips the workflow entirely. - -## Code Quality and Security - -### analyze-changes [🔗](analyze-changes.yaml) - -_Trigger:_ Every day or manually. - -_Action:_ - -* Run [GitHub CodeQL](https://codeql.github.com/) action, upload result to GitHub security tab -- do not apply to pull request, only to `master`, -* Run [Trivy security scanner](https://github.com/aquasecurity/trivy) on built artifacts and upload result to GitHub security tab and Datadog Code Analysis. - -_Notes:_ Results are sent on both production and staging environments. - -### comment-on-submodule-update [🔗](comment-on-submodule-update.yaml) - -_Trigger:_ When creating a PR commits to `master` or a `release/*` branch with a Git Submodule update. - -_Action:_ Notify the PR author through comments that about the Git Submodule update. - -### run-system-tests [🔗](run-system-tests.yaml) - -_Trigger:_ When pushing commits to `master` or manually. - -_Action:_ Build the Java Client Library and runs [the system tests](https://github.com/DataDog/system-tests) against. - -_Recovery:_ Manually trigger the action on the desired branch. - -### update-gradle-dependencies [🔗](update-gradle-dependencies.yaml) - -_Trigger:_ Every week or manually. - -_Action:_ Create a PR updating the Grade dependencies and their locking files. - -_Recovery:_ Manually trigger the action again. - -### update-smoke-test-latest-versions [🔗](update-smoke-test-latest-versions.yaml) - -_Trigger:_ Every week or manually. - -_Action:_ Create a PR updating the pinned "latest" tool versions (Gradle, Maven, Maven Surefire) used by CI Visibility smoke tests. - -_Recovery:_ Manually trigger the action again. - -### update-jmxfetch-submodule [🔗](update-jmxfetch-submodule.yaml) - -_Trigger:_ Monthly or manually - -_Action:_ Creates a PR updating the git submodule at dd-java-agent/agent-jmxfetch/integrations-core - -_Recovery:_ Manually trigger the action again. - -## Maintenance - -GitHub actions should be part of the [repository allowed actions to run](https://github.com/DataDog/dd-trace-java/settings/actions). -While GitHub owned actions are allowed by default, the other ones must be declared. - -Run the following script to get the list of actions to declare according the state of your working copy: -```bash -find .github/workflows -name "*.yaml" -exec awk '/uses:/{print $2 ","}' {} \; | grep -vE '^(actions|github)/' | sed 's/@.*/@*/' | sort | uniq -``` - -## Testing - -Workflows can be locally tested using the [`act` CLI](https://github.com/nektos/act/). -Docker and [GiHub CLI](https://cli.github.com/) need also to be installed. -The [.github/workflows/tests/](./tests) folder contains test scripts and event payloads to locally trigger workflows. - -> [!WARNING] -> Local workflow tests run against the repository and will potentially alter existing issues, milestones and releases. -> Pay extra attention to the workflow jobs you trigger to not create development disruption. diff --git a/.github/workflows/add-milestone-to-pull-requests.yaml b/.github/workflows/add-milestone-to-pull-requests.yaml deleted file mode 100644 index 725652b031d..00000000000 --- a/.github/workflows/add-milestone-to-pull-requests.yaml +++ /dev/null @@ -1,86 +0,0 @@ -name: Add milestone to pull requests -on: - pull_request: - types: [closed] - branches: - - master - - release/v* -jobs: - add_milestone_to_merged: - name: Add milestone to merged pull requests - permissions: - issues: write # Required to update a pull request using the issues API - pull-requests: write # Required to update the milestone of a pull request - if: github.event.pull_request.merged && github.event.pull_request.milestone == null - runs-on: ubuntu-latest - steps: - - name: Add milestone to merged pull requests - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - retries: 3 - retry-exempt-status-codes: 400,401 - script: | - // Get project milestones - const response = await github.rest.issues.listMilestones({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open' - }) - if (!response.data || response.data.length == 0) { - core.setFailed(`Failed to list milestones: ${response.status}`) - return - } - // Get the base branch - const base = '${{ github.event.pull_request.base.ref }}' - // Look for the matching milestone - let milestoneNumber = null - if (base == 'master') { - // Pick the milestone with the highest version as title using semver - milestoneNumber = response.data - .map(milestone => { - // Parse version title as semver ".." - const versionNumbers = milestone.title.match(/^(\d+)\.(\d+)\.(\d+)$/) - if (versionNumbers == null) { - return null - } - milestone.version = { - major: parseInt(versionNumbers[1]), - minor: parseInt(versionNumbers[2]), - patch: parseInt(versionNumbers[3]) - } - return milestone - }) - .filter(milestone => milestone != null) - .sort((a, b) => { - if (a.version.major != b.version.major) { - return a.version.major - b.version.major - } - if (a.version.minor != b.version.minor) { - return a.version.minor - b.version.minor - } - return a.version.patch - b.version.patch - }) - .pop()?.number - } else if (base.startsWith('release/v') && base.endsWith('.x')) { - // Extract the minor version related to the base branch (e.g. "release/v1.2.x" -> "1.2.") - const version = base.substring(9, base.length - 1) - // Pick the milestone with title matching the extracted version - const versionMilestone = response.data - .find(milestone => milestone.title.startsWith(version)) - if (!versionMilestone) { - core.setFailed(`Milestone not found for minor version: ${version}`) - } else { - milestoneNumber = versionMilestone.number - } - } else { - core.setFailed(`Unexpected pull request base: ${base}`) - } - // Update pull request milestone using the issues API (as pull requests are issues) - if (milestoneNumber != null) { - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: ${{ github.event.pull_request.number }}, - milestone: milestoneNumber - }); - } diff --git a/.github/workflows/add-release-to-cloudfoundry.yaml b/.github/workflows/add-release-to-cloudfoundry.yaml deleted file mode 100644 index b26f06b9bbe..00000000000 --- a/.github/workflows/add-release-to-cloudfoundry.yaml +++ /dev/null @@ -1,55 +0,0 @@ -name: Add release to Cloud Foundry -on: - release: - types: - - released -jobs: - update-releases: - permissions: - contents: write # Required to commit and push changes to the repository - runs-on: ubuntu-latest - steps: - - name: Checkout "cloudfoundry" branch - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - with: - ref: cloudfoundry - - name: Get release version - id: get-release-version - env: - TAG_NAME: ${{ github.event.release.tag_name }} - run: echo "VERSION=$(echo ${TAG_NAME/#v/})" >> $GITHUB_OUTPUT - - name: Get release URL - id: get-release-url - run: | - echo "URL=https://repo1.maven.org/maven2/com/datadoghq/dd-java-agent/${{ steps.get-release-version.outputs.VERSION }}/dd-java-agent-${{ steps.get-release-version.outputs.VERSION }}.jar" >> $GITHUB_OUTPUT - - name: Wait for the release to be available - run: | - TRY=0 - MAX_TRIES=60 # Wait up to 30 minutes - DELAY=30 - while [ $TRY -lt $MAX_TRIES ]; do - if curl -s -I ${{ steps.get-release-url.outputs.URL }} | grep -q "^HTTP/.* 200"; then - break - fi - echo "Waiting for the release to be available..." - sleep $DELAY - TRY=$((TRY+1)) - if [ $TRY -eq $MAX_TRIES ]; then - echo "The release is not available after 30 mins. Aborting..." - exit 1 - fi - done - - name: Append release to Cloud Foundry repository - run: | - echo "${{ steps.get-release-version.outputs.VERSION }}: ${{ steps.get-release-url.outputs.URL }}" >> index.yml - - name: Commit changes - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add --all - git commit -m "chore: Add version ${{ steps.get-release-version.outputs.VERSION }} to Cloud Foundry" - - name: Push changes - uses: DataDog/commit-headless@ad3668640012ec69186398f43d61923f6878bbbe # action/v3.2.0 - with: - branch: cloudfoundry - command: push diff --git a/.github/workflows/analyze-changes.yaml b/.github/workflows/analyze-changes.yaml deleted file mode 100644 index 526832b607b..00000000000 --- a/.github/workflows/analyze-changes.yaml +++ /dev/null @@ -1,117 +0,0 @@ -name: Analyze changes - -on: - schedule: - - cron: "0 20 * * *" - workflow_dispatch: - -jobs: - codeql: - name: Analyze changes with GitHub CodeQL - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write # Required to upload the results to the Security tab - - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - with: - submodules: 'recursive' - - name: Cache Gradle dependencies - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - name: Initialize CodeQL - uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 - with: - languages: 'java' - build-mode: 'manual' - - - name: Build dd-trace-java for creating the CodeQL database - env: - ORG_GRADLE_PROJECT_akkaRepositoryToken: ${{ secrets.AKKA_REPO_TOKEN }} - run: | - GRADLE_OPTS="-Dorg.gradle.jvmargs='-Xms2G -Xmx3G'" \ - ./gradlew clean :dd-java-agent:shadowJar --build-cache --parallel --stacktrace --no-daemon --max-workers=4 - - - name: Perform CodeQL Analysis and upload results to GitHub Security tab - uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 - - trivy: - name: Analyze changes with Trivy - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write # Required to upload the results to the Security tab - - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - with: - submodules: 'recursive' - - - name: Cache Gradle dependencies - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - name: Remove old artifacts - run: | - MVN_LOCAL_REPO=$(./mvnw help:evaluate -Dexpression=settings.localRepository -q -DforceStdout) - echo "MVN_LOCAL_REPO=${MVN_LOCAL_REPO}" >> "$GITHUB_ENV" - rm -rf "${MVN_LOCAL_REPO}/com/datadoghq" - - - name: Build and publish artifacts locally - env: - ORG_GRADLE_PROJECT_akkaRepositoryToken: ${{ secrets.AKKA_REPO_TOKEN }} - run: | - GRADLE_OPTS="-Dorg.gradle.jvmargs='-Xms2G -Xmx3G'" \ - ./gradlew clean publishToMavenLocal --build-cache --parallel --stacktrace --no-daemon --max-workers=4 - - - name: Copy published artifacts - run: | - mkdir -p ./workspace/.trivy - cp -RP "${MVN_LOCAL_REPO}/com/datadoghq" ./workspace/.trivy/ - ls -laR "./workspace/.trivy" - - - name: Run Trivy security scanner - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - scan-type: rootfs - scan-ref: './workspace/.trivy/' - format: 'sarif' - output: 'trivy-results.sarif' - severity: 'CRITICAL,HIGH' - limit-severities-for-sarif: true - env: - TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db,public.ecr.aws/aquasecurity/trivy-db - TRIVY_JAVA_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-java-db,public.ecr.aws/aquasecurity/trivy-java-db - - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 - if: always() - with: - sarif_file: 'trivy-results.sarif' - - - name: Upload results to Datadog CI Static Analysis - run: | - wget --no-verbose https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64 -O datadog-ci - chmod +x datadog-ci - ./datadog-ci sarif upload trivy-results.sarif --service dd-trace-java --env ci - env: - DD_API_KEY: ${{ secrets.DATADOG_API_KEY_PROD }} - DD_SITE: datadoghq.com diff --git a/.github/workflows/check-pull-request-labels.yaml b/.github/workflows/check-pull-request-labels.yaml deleted file mode 100644 index fbcc7303afe..00000000000 --- a/.github/workflows/check-pull-request-labels.yaml +++ /dev/null @@ -1,214 +0,0 @@ -name: Validate PR Label Format -on: - pull_request: - types: [opened, edited, ready_for_review, labeled, synchronize] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - check_pr_labels: - name: Check pull request labels - permissions: - issues: write - pull-requests: write - runs-on: ubuntu-latest - steps: - - name: Flag AI-generated pull requests - id: flag_ai_generated - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - // Skip draft pull requests - if (context.payload.pull_request.draft) { - return - } - const prNumber = context.payload.pull_request.number - const owner = context.repo.owner - const repo = context.repo.repo - const aiGeneratedLabel = 'tag: ai generated' - let isAiGenerated = false - let labelsStale = false - - /* - * Check for 'Bits AI' label and remove it. - */ - const bitsAiLabel = 'Bits AI' - const prLabels = context.payload.pull_request.labels.map(l => l.name) - if (prLabels.includes(bitsAiLabel)) { - isAiGenerated = true - // Remove label from the PR - try { - await github.rest.issues.removeLabel({ - owner, repo, - issue_number: prNumber, - name: bitsAiLabel - }) - } catch (e) { - core.warning(`Could not remove '${bitsAiLabel}' label from PR: ${e.message}`) - } - labelsStale = true - // Delete label from the repository - try { - await github.rest.issues.deleteLabel({ owner, repo, name: bitsAiLabel }) - } catch (e) { - core.warning(`Could not delete '${bitsAiLabel}' label from repo: ${e.message}`) - } - } - - /* - * Inspect commits for AI authorship signals. - */ - if (context.payload.pull_request.labels.some(l => l.name === aiGeneratedLabel)) { - core.info(`PR #${prNumber} is already labeled as AI-generated, skipping commit scan.`) - core.setOutput('labels_stale', String(labelsStale)) - return - } - const aiRegex = /\b(anthropic|chatgpt|codex|copilot|cursor|openai)\b/i - const commits = await github.paginate(github.rest.pulls.listCommits, { - owner, repo, - pull_number: prNumber, - per_page: 100 - }) - for (const { commit } of commits) { - const authorName = commit.author?.name ?? '' - const authorEmail = commit.author?.email ?? '' - const committerName = commit.committer?.name ?? '' - const committerEmail = commit.committer?.email ?? '' - // Extract Co-authored-by trailer lines from commit message - const coAuthors = (commit.message ?? '').split('\n') - .filter(line => /^co-authored-by:/i.test(line.trim())) - const fieldsToCheck = [authorName, authorEmail] - // Skip GitHub's generic noreply for committer - if (committerEmail !== 'noreply@github.com') { - fieldsToCheck.push(committerName, committerEmail) - } - fieldsToCheck.push(...coAuthors) - if (fieldsToCheck.some(field => aiRegex.test(field))) { - isAiGenerated = true - break - } - } - - /* - * Add 'tag: ai generated' label if AI-generated. - */ - if (isAiGenerated) { - // Re-fetch labels only if they were modified above (Bits AI removal) - let currentLabels - if (labelsStale) { - const { data: currentPr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber }) - currentLabels = currentPr.labels.map(l => l.name) - } else { - currentLabels = context.payload.pull_request.labels.map(l => l.name) - } - if (!currentLabels.includes(aiGeneratedLabel)) { - try { - await github.rest.issues.addLabels({ - owner, repo, - issue_number: prNumber, - labels: [aiGeneratedLabel] - }) - core.info(`Added '${aiGeneratedLabel}' label to PR #${prNumber}`) - } catch (e) { - core.setFailed(`Could not add '${aiGeneratedLabel}' label to PR #${prNumber}: ${e.message}`) - } - } - } - core.setOutput('labels_stale', String(labelsStale)) - - - name: Check pull request labels - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - env: - LABELS_STALE: ${{ steps.flag_ai_generated.outputs.labels_stale }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - // Skip draft pull requests - if (context.payload.pull_request.draft) { - return - } - // Define valid label categories - const validCategories = [ - 'type:', - 'comp:', - 'inst:', - 'tag:', - 'mergequeue-status:', - 'team:', - 'performance:', // To refactor to 'ci: ' in the future - 'run-tests:' // Unused since GitLab migration - ] - // Exact-match labels that don't fit a category prefix (e.g. labels applied - // by external automation tooling). - const exactAllowlist = [ - 'campaigner-automated-change' - ] - // Re-fetch labels only if the previous step modified them (ex: "Bits AI" removal) - let prLabels - if (process.env.LABELS_STALE === 'true') { - const { data: currentPr } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number - }) - prLabels = currentPr.labels - } else { - prLabels = context.payload.pull_request.labels - } - // Look for invalid labels - const invalidLabels = prLabels - .map(label => label.name) - .filter(label => - !exactAllowlist.includes(label) && - validCategories.every(prefix => !label.startsWith(prefix)) - ) - const hasInvalidLabels = invalidLabels.length > 0 - // Get existing comments to check for blocking comment - const comments = await github.rest.issues.listComments({ - issue_number: context.payload.pull_request.number, - owner: context.repo.owner, - repo: context.repo.repo - }) - const commentMarker = '' - let blockingComment = comments.data.find(comment => comment.body.includes(commentMarker)) - // Create or update blocking comment if there are invalid labels - if (hasInvalidLabels) { - const commentBody = '**PR Blocked - Invalid Label**\n\n' + - `The pull request introduced unexpected labels:\n\n` + - invalidLabels.map(label => `* \`${label}\``).join('\n') + '\n\n' + - '**This PR is blocked until:**\n' + - '1. The invalid labels are deleted, and\n' + - '2. A maintainer deletes this comment to unblock the PR\n\n' + - '**Note:** Simply removing labels from the pull request is not enough - a maintainer must delete this comment then remove the label to remove the block.\n\n' + - commentMarker - - if (blockingComment) { - // Update existing blocking comment - await github.rest.issues.updateComment({ - comment_id: blockingComment.id, - owner: context.repo.owner, - repo: context.repo.repo, - body: commentBody - }) - } else { - // Create new blocking comment - await github.rest.issues.createComment({ - issue_number: context.payload.pull_request.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: commentBody - }) - } - blockingComment = true - } - if (blockingComment) { - // Block the PR by failing the workflow - if (hasInvalidLabels) { - core.setFailed(`PR blocked: Invalid labels detected: (${invalidLabels.join(', ')}). A maintainer must delete the blocking comment after fixing the labels to allow merging.`) - } else { - core.setFailed(`PR blocked: A previous blocking comment still exists. A maintainer must delete it to allow merging.`) - } - } diff --git a/.github/workflows/check-pull-requests.yaml b/.github/workflows/check-pull-requests.yaml deleted file mode 100644 index 42058eb42ab..00000000000 --- a/.github/workflows/check-pull-requests.yaml +++ /dev/null @@ -1,86 +0,0 @@ -name: Check pull requests -on: - pull_request: - types: [opened, edited, ready_for_review, labeled, unlabeled, synchronize] - branches: - - master - - release/v* -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true -jobs: - check_pull_requests: - name: Check pull requests - permissions: - issues: write # Required to create a comment on the pull request - pull-requests: write # Required to create a comment on the pull request - runs-on: ubuntu-latest - steps: - - name: Check pull requests - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - // Skip draft pull requests - if (context.payload.pull_request.draft) { - return - } - // Check at least one type and (component or instrumentation) label is set - const labels = context.payload.pull_request.labels.map(label => label.name) - const ignoreReleaseNotes = labels.filter(label => label == 'tag: no release notes').length > 0 - const hasTypeLabel = labels.filter(label => label.startsWith('type:')).length > 0 - const hasComponentLabel = labels.filter(label => label.startsWith('comp:')).length > 0 - const hasInstrumentationLabel = labels.filter(label => label.startsWith('inst:')).length > 0 - const labelsCheckFailed = !ignoreReleaseNotes && (!hasTypeLabel || (!hasComponentLabel && !hasInstrumentationLabel)); - if (labelsCheckFailed) { - core.setFailed('Please add at least one type, and one component or instrumentation label to the pull request.') - } - // Check title does not contain tag - const title = context.payload.pull_request.title - const titleCheckFailed = title.match(/\[.*\]/) - if (titleCheckFailed) { - core.setFailed('Please remove the tag from the pull request title.') - } - // Check body does - const linkingKeywords = ['closes', 'closed', 'fix', 'fixes', 'fixed', 'resolve', 'resolves', 'resolved'] - const body = context.payload.pull_request.body - const bodyCheckFailed = linkingKeywords.some(keyword => body.search(new RegExp(`${keyword}\\s\\d+`, "im")) !== -1) - if (bodyCheckFailed) { - core.setFailed('Please remove the issue linking keyword from the pull request body.') - } - // Add comment to the pull request - if (labelsCheckFailed || titleCheckFailed || bodyCheckFailed) { - // Define comment body - const commentMarker = '' - const commentBody = 'Hi! 👋 Thanks for your pull request! 🎉\n\n' + - 'To help us review it, please make sure to:\n\n' + - (labelsCheckFailed ? '* Add at least one type, and one component or instrumentation label to the pull request\n' : '') + - (titleCheckFailed ? '* Remove the tag from the pull request title\n' : '') + - (bodyCheckFailed ? '* Remove the issue linking keyword\n' : '') + - '\nIf you need help, please check our [contributing guidelines](https://github.com/DataDog/dd-trace-java/blob/master/CONTRIBUTING.md).' + - '\n\n' + commentMarker - // Look for previous comment - const comments = await github.rest.issues.listComments({ - issue_number: context.payload.pull_request.number, - owner: context.repo.owner, - repo: context.repo.repo - }) - const previousComment = comments.data.find(comment => comment.body.includes(commentMarker)) - if (previousComment) { - // Update previous comment - await github.rest.issues.updateComment({ - comment_id: previousComment.id, - owner: context.repo.owner, - repo: context.repo.repo, - body: commentBody - }) - } else { - // Create new comment - await github.rest.issues.createComment({ - issue_number: context.payload.pull_request.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: commentBody - }) - } - } diff --git a/.github/workflows/comment-on-submodule-update.yaml b/.github/workflows/comment-on-submodule-update.yaml deleted file mode 100644 index c81a3004bf5..00000000000 --- a/.github/workflows/comment-on-submodule-update.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: Comment on Submodule Update - -on: - pull_request: - branches: - - 'master' - - 'release/**' - paths: - - 'dd-java-agent/agent-jmxfetch/integrations-core' - -jobs: - comment_on_submodule_update: - permissions: - issues: write # Required to create a comment on the pull request - pull-requests: write # Required to create a comment on the pull request - runs-on: ubuntu-latest - - steps: - - name: Post comment on submodule update - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'Hi! 👋 Looks like you updated a Git Submodule.\n' + - 'If this was not intentional please make sure to:\n\n' + - '* Update the submodule to the latest commit on the master branch using the `git submodule update` command,\n' + - '* Check you [properly set up your environment for contributing](https://github.com/DataDog/dd-trace-java/blob/master/CONTRIBUTING.md#git-submodule-setup).' - }) diff --git a/.github/workflows/create-release-branch.yaml b/.github/workflows/create-release-branch.yaml deleted file mode 100644 index ecd13a1de93..00000000000 --- a/.github/workflows/create-release-branch.yaml +++ /dev/null @@ -1,141 +0,0 @@ -name: Create Release Branch and Pin System Tests - -on: - push: - tags: - - 'v[0-9]+.[0-9]+.0' # Trigger on minor release tags (e.g. v1.54.0) - workflow_dispatch: - inputs: - tag: - description: 'The minor release tag (e.g. v1.54.0)' - required: true - type: string - -jobs: - create-release-branch: - runs-on: ubuntu-latest - permissions: - contents: write # Allow pushing the release branch - outputs: - release-branch-name: ${{ steps.define-release-branch.outputs.branch }} - steps: - - name: Determine tag - id: determine-tag - run: | - if [ -n "${{ github.event.inputs.tag }}" ]; then - TAG=${{ github.event.inputs.tag }} - else - TAG=${GITHUB_REF#refs/tags/} - fi - if ! [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.0$ ]]; then - echo "Error: Tag $TAG is not in the expected format: vX.Y.0" - exit 1 - fi - echo "tag=${TAG}" >> "$GITHUB_OUTPUT" - - - name: Define release branch name from tag - id: define-release-branch - run: | - TAG=${{ steps.determine-tag.outputs.tag }} - echo "branch=release/${TAG%.0}.x" >> "$GITHUB_OUTPUT" - - - name: Check out repo at tag - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - with: - ref: ${{ steps.determine-tag.outputs.tag }} - - - name: Check if branch already exists - id: check-release-branch - run: | - BRANCH=${{ steps.define-release-branch.outputs.branch }} - if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then - echo "creating_new_branch=false" >> "$GITHUB_OUTPUT" - echo "Branch $BRANCH already exists - skipping creation" - else - echo "creating_new_branch=true" >> "$GITHUB_OUTPUT" - echo "Branch $BRANCH does not exist - creating it now" - fi - - - name: Create and push release branch - if: steps.check-release-branch.outputs.creating_new_branch == 'true' - run: | - git checkout -b "${{ steps.define-release-branch.outputs.branch }}" - git push -u origin "${{ steps.define-release-branch.outputs.branch }}" - - pin-system-tests: - needs: create-release-branch - runs-on: ubuntu-latest - permissions: - contents: write - id-token: write # required for OIDC token federation - steps: - - uses: DataDog/dd-octo-sts-action@96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a # v1.0.4 - id: octo-sts - with: - scope: DataDog/dd-trace-java - policy: self.pin-system-tests.create-pr - - - name: Check out repo at release branch - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - with: - ref: ${{ needs.create-release-branch.outputs.release-branch-name }} - - - name: Get latest commit SHA of base release branch - id: get-latest-commit-sha - run: | - echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - - - name: Define pin-system-tests branch name from date - id: define-pin-branch - run: echo "branch=ci/pin-system-tests-$(date +'%Y%m%d')" >> $GITHUB_OUTPUT - - - name: Check if pin-system-tests branch already exists - id: check-pin-branch - run: | - BRANCH=${{ steps.define-pin-branch.outputs.branch }} - if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then - echo "ERROR: Branch $BRANCH already exists - please delete it and re-run the workflow." - exit 1 - else - echo "Branch $BRANCH does not exist - creating it now." - fi - - - name: Update system-tests references to latest commit SHA of system-tests main - run: ./tooling/update_system_test_reference.sh - - - name: Check if changes should be committed - id: check-changes - run: | - if [[ -z "$(git status -s)" ]]; then - echo "ERROR: No changes to commit - the system-tests reference was not updated." - exit 1 - else - echo "Changes to commit:" - git status -s - fi - - - name: Commit changes - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git commit -m "chore: Pin system-tests for release branch" .github/workflows/run-system-tests.yaml .gitlab-ci.yml - - - name: Push changes - uses: DataDog/commit-headless@ad3668640012ec69186398f43d61923f6878bbbe # action/v3.2.0 - with: - token: "${{ steps.octo-sts.outputs.token }}" - branch: "${{ steps.define-pin-branch.outputs.branch }}" - head-sha: "${{ steps.get-latest-commit-sha.outputs.sha }}" - create-branch: true - command: push - - - name: Create pull request - env: - GH_TOKEN: ${{ steps.octo-sts.outputs.token }} - run: | - gh pr create --title "Pin system tests for release branch" \ - --base ${{ needs.create-release-branch.outputs.release-branch-name }} \ - --head ${{ steps.define-pin-branch.outputs.branch }} \ - --label "tag: dependencies" \ - --label "tag: no release notes" \ - --body "This PR pins the system-tests reference for the release branch." diff --git a/.github/workflows/draft-release-notes-on-tag.yaml b/.github/workflows/draft-release-notes-on-tag.yaml deleted file mode 100644 index d471015ffe4..00000000000 --- a/.github/workflows/draft-release-notes-on-tag.yaml +++ /dev/null @@ -1,186 +0,0 @@ -name: Draft release notes on tag -on: - create: - workflow_dispatch: - -jobs: - draft_release_notes: - name: Draft release notes - permissions: - contents: write # Required to create a release - if: (github.event.ref_type == 'tag' && github.event.master_branch == 'master') || github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - steps: - - name: Get milestone title - id: milestoneTitle - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - result-encoding: string - script: | - // Get the milestone title ("X.Y.Z") from tag name ("vX.Y.Z(-rc)") - const match = '${{github.event.ref}}'.match(/v(\d+\.\d+\.\d+)(-rc\d+)?/i) - if (!match) { - core.setFailed('Failed to parse tag name into milestone name: ${{github.event.ref}}') - return - } - const milestoneTitle = match[1] - const isReleaseCandidate = match[2] !== undefined - - // Look for the milestone - const milestone = (await github.paginate('GET /repos/{owner}/{repo}/milestones', { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'all' - })).find(m => m.title == milestoneTitle) - if (!milestone) { - core.setFailed(`Failed to find milestone: ${milestoneTitle}`) - return - } - - // Get pull requests of the milestone - const pullRequests = (await github.paginate('/repos/{owner}/{repo}/issues', { - owner: context.repo.owner, - repo: context.repo.repo, - milestone: milestone.number, - state: 'closed' - })) - .filter(i => i.pull_request && i.pull_request.merged_at) // Skip closed but not merged - .filter(p => !p.labels.find(label => label.name == 'tag: no release notes')) // Skip excluded - - // Group PR by components and instrumentations - var prByComponents = new Map() - var prByInstrumentations = new Map() - var otherPRs = new Array() - for (let pullRequest of pullRequests) { - var captured = false - for (let label of pullRequest.labels) { - const index = label.name.indexOf(':') - if (index == -1) { - core.notice('Unsupported label: ${label.name}') - continue - } - const labelKey = label.name.substring(0, index) - const labelValue = label.name.slice(index + 1) - var map = null - if (labelKey == 'comp') { - map = prByComponents - } else if (labelKey == 'inst') { - map = prByInstrumentations - } - if (map) { - var prs = map.get(label.description) - if (!prs) { - prs = new Array() - map.set(label.description, prs) - } - prs.push(pullRequest) - captured = true - } - } - if (!captured) { - otherPRs.push(pullRequest) - } - } - - // Sort components and instrumenations - prByComponents = new Map([...prByComponents].sort()); - const lastInstrumentation = 'All other instrumentations' - prByInstrumentations = new Map([...prByInstrumentations].sort( - (a, b) => { - if (a[0] == lastInstrumentation) { - return 1 - } else if (b[0] == lastInstrumentation) { - return -1 - } - return String(a[0]).localeCompare(b[0]) - } - )); - - // Generate changelog - const decorators = { - 'tag: breaking change': ':warning:', - 'tag: experimental': ':test_tube:', - 'tag: diagnostics': ':mag:', - 'tag: performance': ':zap:', - 'tag: security': ':closed_lock_with_key:', - 'type: bug': ':bug:', - 'type: documentation': ':book:', - 'type: enhancement': ':sparkles:', - 'type: feature request': ':bulb:', - 'type: refactoring': ':broom:' - } - function decorate(pullRequest) { - var line = '' - var decorated = false; - for (let label of pullRequest.labels) { - if (decorators[label.name]) { - line += decorators[label.name] - decorated = true - } - } - if (decorated) { - line += ' ' - } - return line - } - function cleanUpTitle(title) { - // Remove tags between brackets - title = title.replace(/\[[^\]]+\]/g, '') - // Remove cherry-pick prefix - if (title.startsWith('🍒 ') && title.includes(' - ')) { - title = title.substring(title.indexOf(' - ') + 3) - } - return title - } - function format(pullRequest) { - var line = `${decorate(pullRequest)}${cleanUpTitle(pullRequest.title)} (#${pullRequest.number} - @${pullRequest.user.login}` - // Add special thanks if community labeled - if (pullRequest.labels.some(label => label.name == "tag: community")) { - line += ` - thanks for the contribution!` - } - line += ')' - return line; - } - - var changelog = '' - if (isReleaseCandidate) { - changelog += '> [!WARNING]\n' + - '> This is a **release candidate** and is **not** intended for use in production. \n' + - 'Please [open an issue](https://github.com/DataDog/dd-trace-java/issues/new) regarding any problems in this release candidate.\n\n' - } - if (prByComponents.size > 0) { - changelog += '# Components\n\n'; - for (let pair of prByComponents) { - changelog += '## '+pair[0]+'\n\n' - for (let pullRequest of pair[1]) { - changelog += '* ' + format(pullRequest) + '\n' - } - changelog += '\n' - } - } - if (prByInstrumentations.size > 0) { - changelog += '# Instrumentations\n\n' - for (let pair of prByInstrumentations) { - changelog += '## '+pair[0]+'\n\n' - for (let pullRequest of pair[1]) { - changelog += '* ' + format(pullRequest) + '\n' - } - changelog += '\n' - } - } - if (otherPRs.length > 0) { - changelog += '# Other changes\n\n' - for (let pullRequest of otherPRs) { - changelog += '* ' + format(pullRequest) + '\n' - } - } - - // Create release with the draft changelog - await github.rest.repos.createRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: '${{ github.event.ref }}', - name: milestoneTitle, - draft: true, - body: changelog - }) diff --git a/.github/workflows/enforce-datadog-merge-queue.yaml b/.github/workflows/enforce-datadog-merge-queue.yaml deleted file mode 100644 index 6577861e271..00000000000 --- a/.github/workflows/enforce-datadog-merge-queue.yaml +++ /dev/null @@ -1,40 +0,0 @@ -name: Enforce Datadog Merge Queue - -on: - pull_request: - types: [opened, synchronize, reopened, enqueued] - branches: - - master - merge_group: - -jobs: - enforce_datadog_merge_queue: - name: Merge queue check - runs-on: ubuntu-latest - permissions: - id-token: write # required for OIDC token federation - steps: - - name: Block GitHub merge queue - if: github.event_name == 'merge_group' - run: | - echo "Merge is handled by the Datadog merge queue system. Use the /merge command to enqueue your PR for merging." - exit 1 - - name: Get OIDC token - if: github.event.action == 'enqueued' - uses: DataDog/dd-octo-sts-action@96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a # v1.0.4 - id: octo-sts - with: - scope: DataDog/dd-trace-java - policy: self.enforce-datadog-merge-queue.comment-pr - - name: Post /merge comment - if: github.event.action == 'enqueued' - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - github-token: ${{ steps.octo-sts.outputs.token }} - script: | - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.pull_request.number, - body: '/merge' - }); diff --git a/.github/workflows/enforce-groovy-migration.yaml b/.github/workflows/enforce-groovy-migration.yaml deleted file mode 100644 index adfb3ff59ce..00000000000 --- a/.github/workflows/enforce-groovy-migration.yaml +++ /dev/null @@ -1,122 +0,0 @@ -name: Enforce Groovy Migration -on: - pull_request: - types: [opened, edited, ready_for_review, labeled, unlabeled, synchronize] - branches: - - master - - 'release/v*' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - enforce_groovy_migration: - name: Enforce Groovy migration - permissions: - issues: write # Required to create a comment on the pull request - pull-requests: write # Required to create a comment on the pull request - runs-on: ubuntu-latest - steps: - - name: Check for new Groovy files - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const managedMarker = '' - - const deleteManagedComment = async () => { - const comments = await github.rest.issues.listComments({ - issue_number: context.payload.pull_request.number, - owner: context.repo.owner, - repo: context.repo.repo - }) - - const existingComment = comments.data.find(comment => - comment.body.includes(managedMarker) - ) - - if (existingComment) { - await github.rest.issues.deleteComment({ - comment_id: existingComment.id, - owner: context.repo.owner, - repo: context.repo.repo - }) - } - } - - // Check for override label — skip all checks if label present - const labels = context.payload.pull_request.labels.map(l => l.name) - if (labels.includes('tag: override-groovy-enforcement')) { - await deleteManagedComment() - console.log('tag: override-groovy-enforcement label detected — skipping all checks.') - return - } - - // Get all files changed in this PR - const allFiles = await github.paginate(github.rest.pulls.listFiles, { - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number - }) - - // Fail if the PR introduces any new .groovy file - // "renamed" only counts when the previous filename was not already Groovy. - const introducedGroovy = allFiles.filter(file => { - if (!file.filename.endsWith('.groovy')) { - return false - } - - if (file.status === 'added' || file.status === 'copied') { - return true - } - - return file.status === 'renamed' && - (!file.previous_filename || !file.previous_filename.endsWith('.groovy')) - }) - - // Fetch existing comments once - const comments = await github.rest.issues.listComments({ - issue_number: context.payload.pull_request.number, - owner: context.repo.owner, - repo: context.repo.repo - }) - - const existingComment = comments.data.find(comment => comment.body.includes(managedMarker)) - - if (introducedGroovy.length > 0) { - const fileList = introducedGroovy - .map(({ filename }) => `- \`${filename}\``) - .join('\n') - const body = `**❌ New Groovy Files Detected**\n\n` + - `Please avoid introducing new \`.groovy\` files to this repository.\n\n` + - `${fileList}\n\n` + - `Instead, rewrite the new file(s) in Java / JUnit. See the [How to Test With JUnit Guide](https://github.com/DataDog/dd-trace-java/blob/master/docs/how_to_test_with_junit.md) for more details.\n\n` + - `If this PR needs an exception, add the \`tag: override-groovy-enforcement\` label to bypass this workflow.\n\n` + - managedMarker - if (existingComment) { - await github.rest.issues.updateComment({ - comment_id: existingComment.id, - owner: context.repo.owner, - repo: context.repo.repo, - body - }) - } else { - await github.rest.issues.createComment({ - issue_number: context.payload.pull_request.number, - owner: context.repo.owner, - repo: context.repo.repo, - body - }) - } - } else if (existingComment) { - await github.rest.issues.deleteComment({ - comment_id: existingComment.id, - owner: context.repo.owner, - repo: context.repo.repo - }) - } - - if (introducedGroovy.length > 0) { - core.setFailed(`${introducedGroovy.length} new Groovy file(s) detected. See PR comment for details. To bypass this workflow, add the 'tag: override-groovy-enforcement' label.`) - } diff --git a/.github/workflows/increment-milestone-on-tag.yaml b/.github/workflows/increment-milestone-on-tag.yaml deleted file mode 100644 index ef4608582d4..00000000000 --- a/.github/workflows/increment-milestone-on-tag.yaml +++ /dev/null @@ -1,64 +0,0 @@ -name: Increment milestones on tag -on: - create -permissions: - issues: write # Required to update milestones - -jobs: - increment_milestone: - if: github.event.ref_type == 'tag' && contains(github.event.ref,'-RC') == false - runs-on: ubuntu-latest - steps: - - name: Close current milestone - id: close-milestone - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - script: | - // Get the milestone title ("X.Y.Z") from tag name ("vX.Y.Z") - const match = '${{github.event.ref}}'.match(/v(\d+\.\d+\.\d+)/i) - if (!match) { - core.setFailed('Failed to parse tag name into milestone title: ${{github.event.ref}}') - return - } - const milestoneTitle = match[1] - // Look for the milestone from its title - const response = await github.rest.issues.listMilestones({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open' - }) - if (!response.data || response.data.length == 0) { - core.setFailed(`Failed to list milestones: ${response.status}`) - return - } - const milestone = response.data.find(milestone => milestone.title == milestoneTitle) - if (!milestone) { - core.setFailed(`Failed to find milestone: ${milestoneTitle}`) - return - } - // Close the milestone - await github.rest.issues.updateMilestone({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'closed', - milestone_number: milestone.number - }).catch(error => { - core.setFailed(`Failed to close milestone: ${error}`) - }) - // Compute the next milestone version - const versionNumbers = milestoneTitle.split('.').map(Number) - if (versionNumbers[2] != 0) { - core.info('Closing a patch version milestone. Not opening a new one.') - return - } - versionNumbers[1]++ - const nextMilestoneTitle = versionNumbers.join('.') - core.info(`Creating next version milestone: ${nextMilestoneTitle}`) - // Create the next milestone - await github.rest.issues.createMilestone({ - owner: context.repo.owner, - repo: context.repo.repo, - title: nextMilestoneTitle - }).catch(error => { - core.setFailed(`Failed to create milestone ${nextMilestoneTitle}: ${error}`) - }) diff --git a/.github/workflows/prune-old-pull-requests.yaml b/.github/workflows/prune-old-pull-requests.yaml deleted file mode 100644 index e5633a39415..00000000000 --- a/.github/workflows/prune-old-pull-requests.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: Prune old pull requests -on: - schedule: - - cron: '0 3 1 * *' - workflow_dispatch: - -jobs: - prune-old-pull-requests: - name: Prune old pull requests - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - name: Prune old pull requests - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 - with: - days-before-stale: -1 # Disable general stale bot - days-before-pr-stale: 90 # Only enable stale bot for PRs with no activity for 90 days - stale-pr-message: 'This pull request has been marked as stale because it has not had activity over the past quarter. It will be closed in 7 days if no further activity occurs. Feel free to reopen the PR if you are still working on it.' - close-pr-message: 'This pull request has been closed because it has not had activity over the past quarter. Feel free to reopen the PR if you are still working on it.' - stale-pr-label: 'tag: stale' - operations-per-run: 500 diff --git a/.github/workflows/run-system-tests.yaml b/.github/workflows/run-system-tests.yaml deleted file mode 100644 index 2c441f495de..00000000000 --- a/.github/workflows/run-system-tests.yaml +++ /dev/null @@ -1,102 +0,0 @@ -name: Run system tests - -on: - merge_group: - pull_request: - workflow_dispatch: - schedule: - - cron: 0 4 * * * - push: - branches: - - master - -# Cancel long-running jobs when a new commit is pushed -concurrency: - # this ensures that only one workflow runs at a time for a given branch on pull requests - # as the group key is the workflow name and the branch name - # for scheduled runs and pushes to master, we use the run id to ensure that all runs are executed - group: ${{ (github.event_name == 'pull_request' && format('{0}-{1}', github.workflow, github.ref)) || format('{0}-{1}', github.workflow, github.run_id) }} - cancel-in-progress: true - -jobs: - build: - runs-on: - group: APM Larger Runners - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - with: - submodules: 'recursive' - fetch-depth: 0 - - - name: Cache Gradle dependencies - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - name: Build dd-trace-java - env: - ORG_GRADLE_PROJECT_akkaRepositoryToken: ${{ secrets.AKKA_REPO_TOKEN }} - run: | - GRADLE_OPTS="-Xms2g -Xmx4g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC" \ - JAVA_HOME=$JAVA_HOME_8_X64 \ - JAVA_8_HOME=$JAVA_HOME_8_X64 \ - JAVA_11_HOME=$JAVA_HOME_11_X64 \ - JAVA_17_HOME=$JAVA_HOME_17_X64 \ - JAVA_21_HOME=$JAVA_HOME_21_X64 \ - ./gradlew clean :dd-java-agent:shadowJar \ - --build-cache --parallel --stacktrace --no-daemon --max-workers=4 - - - name: Upload artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a - with: - name: binaries - path: workspace/dd-java-agent/build/libs/ - - main: - needs: - - build - # If you change the following comment, update the pattern in the update_system_test_reference.sh script to match. - uses: DataDog/system-tests/.github/workflows/system-tests.yml@main # system tests are pinned on release branches only - permissions: - contents: read - id-token: write - packages: write - with: - library: java - # If you change the following comment, update the pattern in the update_system_test_reference.sh script to match. - ref: "main" # system tests are pinned on release branches only - binaries_artifact: binaries - desired_execution_time: 900 # 15 minutes - scenarios_groups: tracer-release - excluded_scenarios: APM_TRACING_E2E_OTEL,APM_TRACING_E2E_SINGLE_SPAN,PROFILING # exclude flaky scenarios - skip_empty_scenarios: ${{ github.event_name != 'push' && github.event_name != 'schedule' }} - push_to_test_optimization: true - secrets: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - - # Ensure the main job is run to completion - check: - name: Check system tests success - runs-on: ubuntu-latest - if: ${{ always() }} - needs: [build, main] - steps: - - name: Fail if build failed - if: ${{ needs.build.result != 'success' }} - run: | - echo "❌ Build job did not succeed: ${{ needs.build.result }}" - exit 1 - - name: Fail if main failed or is skipped - if: ${{ needs.main.result != 'success' }} - run: | - echo "❌ Main job did not succeed: ${{ needs.main.result }}" - exit 1 - - name: Success - run: echo "✅ All required jobs succeeded." diff --git a/.github/workflows/tests/add-milestone-to-pull-requests/payload-pull-request.json b/.github/workflows/tests/add-milestone-to-pull-requests/payload-pull-request.json deleted file mode 100644 index a8c6ca4788f..00000000000 --- a/.github/workflows/tests/add-milestone-to-pull-requests/payload-pull-request.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "pull_request": { - "number": 7549, - "base": { - "ref": "master" - }, - "merged": true - } -} diff --git a/.github/workflows/tests/add-milestone-to-pull-requests/test-pull-request.sh b/.github/workflows/tests/add-milestone-to-pull-requests/test-pull-request.sh deleted file mode 100755 index cc7c8ff0c96..00000000000 --- a/.github/workflows/tests/add-milestone-to-pull-requests/test-pull-request.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -source "$(dirname "$0")/../env.sh" -testworkflow pull_request diff --git a/.github/workflows/tests/check-pull-requests/payload-pull-request-draft.json b/.github/workflows/tests/check-pull-requests/payload-pull-request-draft.json deleted file mode 100644 index c81fb0df419..00000000000 --- a/.github/workflows/tests/check-pull-requests/payload-pull-request-draft.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "pull_request": { - "number": 7884, - "draft": true, - "labels": [], - "title": "Adding some new features", - "body": "# What Does This Do\n\nThis PR introduces a workflow that checks PRs contributing guidelines." - } -} diff --git a/.github/workflows/tests/check-pull-requests/payload-pull-request-instrumentation.json b/.github/workflows/tests/check-pull-requests/payload-pull-request-instrumentation.json deleted file mode 100644 index 9ea97e145c6..00000000000 --- a/.github/workflows/tests/check-pull-requests/payload-pull-request-instrumentation.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "pull_request": { - "number": 7884, - "draft": false, - "labels": [ - { - "name": "inst: java" - }, - { - "name": "type: bug" - } - ], - "title": "Adding some new features", - "body": "# What Does This Do\n\nThis PR introduces a workflow that checks PRs contributing guidelines." - } -} diff --git a/.github/workflows/tests/check-pull-requests/payload-pull-request-linking-issue.json b/.github/workflows/tests/check-pull-requests/payload-pull-request-linking-issue.json deleted file mode 100644 index 1d4b389883b..00000000000 --- a/.github/workflows/tests/check-pull-requests/payload-pull-request-linking-issue.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "pull_request": { - "number": 7884, - "draft": false, - "labels": [ - { - "name": "comp: api" - }, - { - "name": "type: enhancement" - } - ], - "title": "Adding some new features", - "body": "# What Does This Do\n\nThis PR introduces a workflow to check that PRs labels and title match the contributing guidelines.\nIt fixes #1234 amoung other issues." - } -} diff --git a/.github/workflows/tests/check-pull-requests/payload-pull-request-missing-label.json b/.github/workflows/tests/check-pull-requests/payload-pull-request-missing-label.json deleted file mode 100644 index 0f3262b688b..00000000000 --- a/.github/workflows/tests/check-pull-requests/payload-pull-request-missing-label.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "pull_request": { - "number": 7884, - "draft": false, - "labels": [ - { - "name": "comp: api" - } - ], - "title": "Adding some new features", - "body": "# What Does This Do\n\nThis PR introduces a workflow that checks PRs contributing guidelines." - } -} diff --git a/.github/workflows/tests/check-pull-requests/payload-pull-request-no-release-notes.json b/.github/workflows/tests/check-pull-requests/payload-pull-request-no-release-notes.json deleted file mode 100644 index 2ea4f92b89e..00000000000 --- a/.github/workflows/tests/check-pull-requests/payload-pull-request-no-release-notes.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "pull_request": { - "number": 7884, - "draft": false, - "labels": [ - { - "name": "tag: no release notes" - } - ], - "title": "Adding some new features", - "body": "# What Does This Do\n\nThis PR introduces a workflow that checks PRs contributing guidelines." - } -} diff --git a/.github/workflows/tests/check-pull-requests/payload-pull-request-title-tag.json b/.github/workflows/tests/check-pull-requests/payload-pull-request-title-tag.json deleted file mode 100644 index 0ba19508205..00000000000 --- a/.github/workflows/tests/check-pull-requests/payload-pull-request-title-tag.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "pull_request": { - "number": 7884, - "draft": false, - "labels": [ - { - "name": "comp: api" - }, - { - "name": "type: enhancement" - } - ], - "title": "[API] Adding some new features", - "body": "# What Does This Do\n\nThis PR introduces a workflow that checks PRs contributing guidelines." - } -} diff --git a/.github/workflows/tests/check-pull-requests/payload-pull-request.json b/.github/workflows/tests/check-pull-requests/payload-pull-request.json deleted file mode 100644 index 38c55efb94e..00000000000 --- a/.github/workflows/tests/check-pull-requests/payload-pull-request.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "pull_request": { - "number": 7884, - "draft": false, - "labels": [ - { - "name": "comp: api" - }, - { - "name": "type: enhancement" - } - ], - "title": "Adding some new features", - "body": "# What Does This Do\n\nThis PR introduces a workflow that checks PRs contributing guidelines." - } -} diff --git a/.github/workflows/tests/check-pull-requests/test-pull-request.sh b/.github/workflows/tests/check-pull-requests/test-pull-request.sh deleted file mode 100755 index f37935140a6..00000000000 --- a/.github/workflows/tests/check-pull-requests/test-pull-request.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -source "$(dirname "$0")/../env.sh" -testworkflow pull_request && \ -testworkflow pull_request instrumentation && \ -testworkflow pull_request draft && \ -testworkflow pull_request no-release-notes && \ -! testworkflow pull_request missing-label && \ -! testworkflow pull_request title-tag && \ -! testworkflow pull_request linking-issue diff --git a/.github/workflows/tests/env.sh b/.github/workflows/tests/env.sh deleted file mode 100644 index 4d10c4b91b3..00000000000 --- a/.github/workflows/tests/env.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -function testworkflow() { - local EVENT_TYPE=$1 - local SCENARIO=$2 - # Get workflow name - local TEST_PATH - TEST_PATH=$(dirname "$(readlink -f "${BASH_SOURCE[1]}")") - local WORKFLOW_NAME - WORKFLOW_NAME=$(basename "$TEST_PATH") - local WORKFLOW_FILE=.github/workflows/${WORKFLOW_NAME}.yaml - local PAYLOAD_FILE - PAYLOAD_FILE=${TEST_PATH}/payload-${EVENT_TYPE//_/-} - if [ "$SCENARIO" != "" ]; then - PAYLOAD_FILE=${PAYLOAD_FILE}-${SCENARIO} - fi - PAYLOAD_FILE=${PAYLOAD_FILE}.json - # Move to project root directory - local FILE_PATH - FILE_PATH=$(dirname "$0") - pushd "$FILE_PATH/../../../../" || exit 1 - # Check if workflow file and payload file exist - if [ ! -f "$WORKFLOW_FILE" ]; then - echo "Workflow file not found: $WORKFLOW_FILE" - exit 1 - fi - if [ ! -f "$PAYLOAD_FILE" ]; then - echo "Payload file not found: $PAYLOAD_FILE" - exit 1 - fi - # Run workflow using act - act "${EVENT_TYPE}" \ - --workflows "${WORKFLOW_FILE}" \ - --eventpath "${PAYLOAD_FILE}" \ - --container-architecture linux/amd64 \ - --secret GITHUB_TOKEN="$(gh auth token)" \ - --verbose - # Capture the exit code - local EXIT_CODE=$? - # Move back to initial directory - popd || exit 1 - # Return the test exit code - return $EXIT_CODE -} diff --git a/.github/workflows/tests/increment-milestone-on-tag/payload-create.json b/.github/workflows/tests/increment-milestone-on-tag/payload-create.json deleted file mode 100644 index 5e4e6c99737..00000000000 --- a/.github/workflows/tests/increment-milestone-on-tag/payload-create.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "ref_type": "tag", - "ref": "v1.40.0" -} diff --git a/.github/workflows/tests/increment-milestone-on-tag/test-create.sh b/.github/workflows/tests/increment-milestone-on-tag/test-create.sh deleted file mode 100755 index c1710568457..00000000000 --- a/.github/workflows/tests/increment-milestone-on-tag/test-create.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -source "$(dirname "$0")/../env.sh" -testworkflow create diff --git a/.github/workflows/tests/update-issues-on-release/payload-release.json b/.github/workflows/tests/update-issues-on-release/payload-release.json deleted file mode 100644 index 5bec147ff18..00000000000 --- a/.github/workflows/tests/update-issues-on-release/payload-release.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "release": { - "name": "1.39.0", - "html_url": "https://github.com/DataDog/dd-trace-java/releases/tag/v1.39.0" - } -} diff --git a/.github/workflows/tests/update-issues-on-release/payload-workflow-dispatch.json b/.github/workflows/tests/update-issues-on-release/payload-workflow-dispatch.json deleted file mode 100644 index 2451023d678..00000000000 --- a/.github/workflows/tests/update-issues-on-release/payload-workflow-dispatch.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "inputs": { - "milestone": "1.39.0" - } -} diff --git a/.github/workflows/tests/update-issues-on-release/test-release.sh b/.github/workflows/tests/update-issues-on-release/test-release.sh deleted file mode 100755 index 830ab75125a..00000000000 --- a/.github/workflows/tests/update-issues-on-release/test-release.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -source "$(dirname "$0")/../env.sh" -testworkflow release diff --git a/.github/workflows/tests/update-issues-on-release/test-workflow-dispatch.sh b/.github/workflows/tests/update-issues-on-release/test-workflow-dispatch.sh deleted file mode 100755 index fbf3f422a6f..00000000000 --- a/.github/workflows/tests/update-issues-on-release/test-workflow-dispatch.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -source "$(dirname "$0")/../env.sh" -testworkflow workflow_dispatch diff --git a/.github/workflows/update-download-releases.yaml b/.github/workflows/update-download-releases.yaml deleted file mode 100644 index 77d07570963..00000000000 --- a/.github/workflows/update-download-releases.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Update download releases -on: - release: - types: - - released - workflow_dispatch: -concurrency: # Avoid running multiple instances to prevent asset conflicts - group: ${{ github.workflow }} -jobs: - update-releases: - permissions: - contents: write # Required to update releases content - runs-on: ubuntu-latest - steps: - - name: Update download releases - if: ${{ github.event_name == 'workflow_dispatch' || ( !github.event.release.draft && !github.event.release.prerelease && !startsWith(github.event.release.name, 'download-latest') ) }} - uses: DataDog/download-release-action@eeefd56e9d1f0102ad1e6f6c8a170c7bfbc5b613 # 0.0.3 diff --git a/.github/workflows/update-gradle-dependencies.yaml b/.github/workflows/update-gradle-dependencies.yaml deleted file mode 100644 index 001c5b38d4e..00000000000 --- a/.github/workflows/update-gradle-dependencies.yaml +++ /dev/null @@ -1,166 +0,0 @@ -name: Update Gradle dependencies -on: - schedule: - - cron: "0 4 * * 0" - workflow_dispatch: - -jobs: - update-gradle-dependencies: - runs-on: ubuntu-latest - name: Update Gradle dependencies - permissions: - contents: read - id-token: write # Required for OIDC token federation - steps: - - uses: DataDog/dd-octo-sts-action@96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a # v1.0.4 - id: octo-sts - with: - scope: DataDog/dd-trace-java - policy: self.update-gradle-dependencies.create-pr - - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - with: - submodules: "recursive" - - - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 - with: - distribution: 'temurin' - java-version: '21' - cache: 'gradle' - - - name: Configure git - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - - name: Define branch names - id: define-branches - run: | - DATE=$(date +'%Y%m%d') - echo "core_branch=ci/update-gradle-dependencies-${DATE}" >> $GITHUB_OUTPUT - echo "instrumentation_branch=ci/update-gradle-dependencies-instrumentation-${DATE}" >> $GITHUB_OUTPUT - - - name: Update Gradle dependencies - env: - ORG_GRADLE_PROJECT_akkaRepositoryToken: ${{ secrets.AKKA_REPO_TOKEN }} - run: | - find . -name 'gradle.lockfile' -delete - GRADLE_OPTS="-Dorg.gradle.jvmargs='-Xms2G -Xmx3G'" \ - ./gradlew resolveAndLockAll --write-locks --parallel --stacktrace --no-daemon --max-workers=4 - - - name: Save instrumentation lock files - run: | - mkdir -p /tmp/instrumentation-lockfiles - find dd-smoke-tests dd-java-agent/instrumentation -name 'gradle.lockfile' -exec cp --parents {} /tmp/instrumentation-lockfiles/ \; - # Restore instrumentation dirs to original state (keep only core changes) - git restore -- 'dd-smoke-tests/' 'dd-java-agent/instrumentation/' - - # ==================== Core modules PR ==================== - - name: Check if core changes exist - id: check-core-changes - run: | - if [[ -z "$(git status -s)" ]]; then - echo "No core changes to commit." - echo "commit_changes=false" >> "$GITHUB_OUTPUT" - else - echo "commit_changes=true" >> "$GITHUB_OUTPUT" - fi - - - name: Create core commit - if: steps.check-core-changes.outputs.commit_changes == 'true' - run: | - git add --all - git commit -m "chore: Update Gradle dependencies" - - - name: Push core changes - if: steps.check-core-changes.outputs.commit_changes == 'true' - uses: DataDog/commit-headless@ad3668640012ec69186398f43d61923f6878bbbe # action/v3.2.0 - with: - token: "${{ steps.octo-sts.outputs.token }}" - branch: "${{ steps.define-branches.outputs.core_branch }}" - head-sha: "${{ github.sha }}" - create-branch: true - command: push - - - name: Create core pull request - if: steps.check-core-changes.outputs.commit_changes == 'true' - env: - GH_TOKEN: ${{ steps.octo-sts.outputs.token }} - run: | - gh pr create --title "Update Gradle dependencies" \ - --base master \ - --head ${{ steps.define-branches.outputs.core_branch }} \ - --label "tag: dependencies" \ - --label "tag: no release notes" \ - --body "$(cat <<'EOF' - # What Does This Do - - This PR updates the Gradle dependency locks for common and product modules. - - # Motivation - - Refresh Gradle dependencies to make sure to apply the latest version available when bumping dependencies. - - # Contributor Checklist - - - [ ] Update PR title if a code change is needed to support one of those new dependencies - EOF - )" - - # ==================== Instrumentation PR ==================== - - name: Reset and apply instrumentation changes - run: | - git reset --hard ${{ github.sha }} - cp -r /tmp/instrumentation-lockfiles/* . - - - name: Check if instrumentation changes exist - id: check-instrumentation-changes - run: | - if [[ -z "$(git status -s)" ]]; then - echo "No instrumentation changes to commit." - echo "commit_changes=false" >> "$GITHUB_OUTPUT" - else - echo "commit_changes=true" >> "$GITHUB_OUTPUT" - fi - - - name: Create instrumentation commit - if: steps.check-instrumentation-changes.outputs.commit_changes == 'true' - run: | - git add --all - git commit -m "chore: Update instrumentation Gradle dependencies" - - - name: Push instrumentation changes - if: steps.check-instrumentation-changes.outputs.commit_changes == 'true' - uses: DataDog/commit-headless@ad3668640012ec69186398f43d61923f6878bbbe # action/v3.2.0 - with: - token: "${{ steps.octo-sts.outputs.token }}" - branch: "${{ steps.define-branches.outputs.instrumentation_branch }}" - head-sha: "${{ github.sha }}" - create-branch: true - command: push - - - name: Create instrumentation pull request - if: steps.check-instrumentation-changes.outputs.commit_changes == 'true' - env: - GH_TOKEN: ${{ steps.octo-sts.outputs.token }} - run: | - gh pr create --title "Update instrumentation Gradle dependencies" \ - --base master \ - --head ${{ steps.define-branches.outputs.instrumentation_branch }} \ - --label "tag: dependencies" \ - --label "tag: no release notes" \ - --body "$(cat <<'EOF' - # What Does This Do - - This PR updates the Gradle dependency locks for instrumentations and their tests. - - # Motivation - - Refresh Gradle dependencies to make sure to test latest versions of dependencies within their supported versions. - - # Contributor Checklist - - - [ ] Update PR title if a code change is needed to support one of those new dependencies - EOF - )" diff --git a/.github/workflows/update-issues-on-release.yaml b/.github/workflows/update-issues-on-release.yaml deleted file mode 100644 index 8ed8a9de1b1..00000000000 --- a/.github/workflows/update-issues-on-release.yaml +++ /dev/null @@ -1,73 +0,0 @@ -name: Update issues on release -on: - release: - types: [released] - workflow_dispatch: - inputs: - milestone: - required: true - default: "0.0.0" - -jobs: - update_issues: - permissions: - issues: write # Required to update issues - runs-on: ubuntu-latest - steps: - - name: Get milestone for release - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - // Get release milestone name - const milestoneName = "${{github.event_name}}" == "workflow_dispatch" ? - "${{github.event.inputs.milestone}}" : - "${{github.event.release.name}}" - // Get release URL - const releaseURL = "${{github.event_name}}" == "workflow_dispatch" ? - "${{github.event.repository.html_url}}/releases/tag/v${{github.event.release.name}}" : - "${{github.event.release.html_url}}" - core.info(`Notify of release availability: v${milestoneName}`) - // Get release milestone number - const milestoneNumber = await github.paginate(github.rest.issues.listMilestones, { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'all' - }, (response, done) => { - const releaseMilestone = response.data.find(milestone => milestone.title == milestoneName) - if (releaseMilestone) { - done() - return releaseMilestone.number - } - }).then(milestones => milestones.pop()) - if (!milestoneNumber) { - core.setFailed(`Failed to find milestone: ${milestoneName}`) - return - } - // Get all release milestone issues - const issues = await github.paginate(github.rest.issues.listForRepo, { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'all', - milestone: milestoneNumber - }, (response) => response.data.filter(issue => !issue["pull_request"])) - // Comment and close issues - for (const issue of issues) { - core.info(issue.state == 'open' ? - `Commenting and closing issue ${issue.number}` : - `Commenting on closed issue ${issue.number}`) - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue.number, - body: `:robot: This issue has been addressed in the latest release. Check full details in the [Release Notes](${releaseURL}).` - }) - if (issue.state == 'open') { - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue.number, - state: 'closed' - }) - } - } diff --git a/.github/workflows/update-jmxfetch-submodule.yaml b/.github/workflows/update-jmxfetch-submodule.yaml deleted file mode 100644 index 0907cb98f84..00000000000 --- a/.github/workflows/update-jmxfetch-submodule.yaml +++ /dev/null @@ -1,69 +0,0 @@ -name: Update jmxfetch integrations submodule - -on: - schedule: - - cron: '0 0 1 * *' - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write # Required for OIDC token federation - steps: - - uses: DataDog/dd-octo-sts-action@96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a # v1.0.4 - id: octo-sts - with: - scope: DataDog/dd-trace-java - policy: self.update-jmxfetch-submodule.create-pr - - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - - - name: Update Submodule - run: | - git submodule update --remote -- dd-java-agent/agent-jmxfetch/integrations-core - - name: Check if changes should be committed - id: check-changes - run: | - if [[ -z "$(git status -s)" ]]; then - echo "No changes to commit, exiting." - echo "commit_changes=false" >> "$GITHUB_OUTPUT" - exit 0 - else - echo "commit_changes=true" >> "$GITHUB_OUTPUT" - fi - - name: Pick a branch name - if: steps.check-changes.outputs.commit_changes == 'true' - id: define-branch - run: echo "branch=ci/update-jmxfetch-submodule-$(date +'%Y%m%d')" >> $GITHUB_OUTPUT - - name: Commit changes - if: steps.check-changes.outputs.commit_changes == 'true' - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git commit -m "feat(ci): Update agent-jmxfetch submodule" dd-java-agent/agent-jmxfetch/integrations-core - - name: Push changes - uses: DataDog/commit-headless@ad3668640012ec69186398f43d61923f6878bbbe # action/v3.2.0 - if: steps.check-changes.outputs.commit_changes == 'true' - with: - token: "${{ steps.octo-sts.outputs.token }}" - branch: "${{ steps.define-branch.outputs.branch }}" - # for scheduled runs, sha is the tip of the default branch - # for dispatched runs, sha is the tip of the branch it was dispatched on - head-sha: "${{ github.sha }}" - create-branch: true - command: push - - name: Create pull request - if: steps.check-changes.outputs.commit_changes == 'true' - env: - GH_TOKEN: ${{ steps.octo-sts.outputs.token }} - run: | - gh pr create --title "Update agent-jmxfetch submodule" \ - --base master \ - --head ${{ steps.define-branch.outputs.branch }} \ - --label "comp: tooling" \ - --label "type: enhancement" \ - --label "tag: no release notes" \ - --body "This PR updates the agent-jmxfetch submodule." diff --git a/.github/workflows/update-smoke-test-latest-versions.yaml b/.github/workflows/update-smoke-test-latest-versions.yaml deleted file mode 100644 index 98a317a23ee..00000000000 --- a/.github/workflows/update-smoke-test-latest-versions.yaml +++ /dev/null @@ -1,175 +0,0 @@ -name: Update smoke test latest versions -on: - schedule: - - cron: "0 5 * * 0" - workflow_dispatch: - -jobs: - update-smoke-test-latest-versions: - runs-on: ubuntu-latest - name: Update smoke test latest versions - env: - MIN_DEPENDENCY_AGE_HOURS: 48 - permissions: - contents: read - id-token: write # Required for OIDC token federation - steps: - - uses: DataDog/dd-octo-sts-action@96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a # v1.0.4 - id: octo-sts - with: - scope: DataDog/dd-trace-java - policy: self.update-smoke-test-latest-versions.create-pr - - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 - - - name: Define branch name - id: define-branch - run: | - DATE=$(date +'%Y%m%d') - echo "branch=ci/update-smoke-test-latest-versions-${DATE}" >> "$GITHUB_OUTPUT" - - - name: Read current pinned versions - id: current - run: | - gradle_props="dd-smoke-tests/gradle/src/test/resources/latest-tool-versions.properties" - maven_props="dd-smoke-tests/maven/src/test/resources/latest-tool-versions.properties" - get_prop() { grep "^$1=" "$2" 2>/dev/null | cut -d= -f2 || true; } - echo "gradle_version=$(get_prop gradle.version "$gradle_props")" >> "$GITHUB_OUTPUT" - echo "maven_version=$(get_prop maven.version "$maven_props")" >> "$GITHUB_OUTPUT" - echo "surefire_version=$(get_prop maven-surefire.version "$maven_props")" >> "$GITHUB_OUTPUT" - - - name: Resolve latest eligible Gradle version - id: gradle - run: | - python3 .github/scripts/dependency_age.py select-gradle \ - --min-age-hours "${MIN_DEPENDENCY_AGE_HOURS}" \ - --current-version "${{ steps.current.outputs.gradle_version }}" \ - --github-output "$GITHUB_OUTPUT" - - - name: Resolve latest eligible stable Maven version - id: maven - run: | - python3 .github/scripts/dependency_age.py select-maven \ - --group-id org.apache.maven \ - --artifact-id apache-maven \ - --prerelease-pattern alpha \ - --prerelease-pattern beta \ - --prerelease-pattern rc \ - --min-age-hours "${MIN_DEPENDENCY_AGE_HOURS}" \ - --current-version "${{ steps.current.outputs.maven_version }}" \ - --github-output "$GITHUB_OUTPUT" - - - name: Resolve latest eligible stable Maven Surefire version - id: surefire - run: | - python3 .github/scripts/dependency_age.py select-maven \ - --group-id org.apache.maven.plugins \ - --artifact-id maven-surefire-plugin \ - --prerelease-pattern alpha \ - --prerelease-pattern beta \ - --min-age-hours "${MIN_DEPENDENCY_AGE_HOURS}" \ - --current-version "${{ steps.current.outputs.surefire_version }}" \ - --github-output "$GITHUB_OUTPUT" - - - name: Update properties files - id: update - env: - GRADLE_VERSION: ${{ steps.gradle.outputs.version }} - GRADLE_PUBLISHED: ${{ steps.gradle.outputs.published_at }} - MAVEN_VERSION: ${{ steps.maven.outputs.version }} - MAVEN_PUBLISHED: ${{ steps.maven.outputs.published_at }} - SUREFIRE_VERSION: ${{ steps.surefire.outputs.version }} - SUREFIRE_PUBLISHED: ${{ steps.surefire.outputs.published_at }} - run: | - version_line() { if [ -n "$2" ]; then echo "$1 (published $2)"; else echo "$1 (unchanged)"; fi; } - echo "Writing latest eligible stable versions (>=${MIN_DEPENDENCY_AGE_HOURS}h old) to properties files:" - echo " Gradle: $(version_line "${GRADLE_VERSION}" "${GRADLE_PUBLISHED}")" - echo " Maven: $(version_line "${MAVEN_VERSION}" "${MAVEN_PUBLISHED}")" - echo " Maven Surefire: $(version_line "${SUREFIRE_VERSION}" "${SUREFIRE_PUBLISHED}")" - - # Build version lines for PR body - echo "gradle_line=$(version_line "${GRADLE_VERSION}" "${GRADLE_PUBLISHED}")" >> "$GITHUB_OUTPUT" - echo "maven_line=$(version_line "${MAVEN_VERSION}" "${MAVEN_PUBLISHED}")" >> "$GITHUB_OUTPUT" - echo "surefire_line=$(version_line "${SUREFIRE_VERSION}" "${SUREFIRE_PUBLISHED}")" >> "$GITHUB_OUTPUT" - - printf '%s\n' \ - "# Pinned latest eligible stable versions (>=${MIN_DEPENDENCY_AGE_HOURS}h old) for CI Visibility Gradle smoke tests." \ - "# Updated automatically by the update-smoke-test-latest-versions workflow." \ - "gradle.version=${GRADLE_VERSION}" \ - > dd-smoke-tests/gradle/src/test/resources/latest-tool-versions.properties - - printf '%s\n' \ - "# Pinned latest eligible stable versions (>=${MIN_DEPENDENCY_AGE_HOURS}h old) for CI Visibility Maven smoke tests." \ - "# Updated automatically by the update-smoke-test-latest-versions workflow." \ - "maven.version=${MAVEN_VERSION}" \ - "maven-surefire.version=${SUREFIRE_VERSION}" \ - > dd-smoke-tests/maven/src/test/resources/latest-tool-versions.properties - - - name: Check for changes - id: check-changes - run: | - if [[ -z "$(git status -s)" ]]; then - echo "No changes detected — pinned versions are already on the latest eligible stable releases." - echo "has_changes=false" >> "$GITHUB_OUTPUT" - else - echo "Changes detected in the following files:" - git status -s - echo "" - echo "Diff:" - git diff - echo "has_changes=true" >> "$GITHUB_OUTPUT" - fi - - - name: Configure git - if: steps.check-changes.outputs.has_changes == 'true' - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - - name: Create commit - if: steps.check-changes.outputs.has_changes == 'true' - run: | - git add dd-smoke-tests/gradle/src/test/resources/latest-tool-versions.properties \ - dd-smoke-tests/maven/src/test/resources/latest-tool-versions.properties - git commit -m "chore: Update smoke test latest tool versions" - - - name: Push changes - if: steps.check-changes.outputs.has_changes == 'true' - uses: DataDog/commit-headless@ad3668640012ec69186398f43d61923f6878bbbe # action/v3.2.0 - with: - token: "${{ steps.octo-sts.outputs.token }}" - branch: "${{ steps.define-branch.outputs.branch }}" - head-sha: "${{ github.sha }}" - create-branch: true - command: push - - - name: Create pull request - if: steps.check-changes.outputs.has_changes == 'true' - env: - GH_TOKEN: ${{ steps.octo-sts.outputs.token }} - run: | - gh pr create --title "Update smoke test latest tool versions" \ - --base master \ - --head ${{ steps.define-branch.outputs.branch }} \ - --label "tag: dependencies" \ - --label "tag: no release notes" \ - --body "$(cat <<'EOF' - # What Does This Do - - This PR updates the pinned latest eligible stable tool versions used by CI Visibility smoke tests. - Only releases at least ${{ env.MIN_DEPENDENCY_AGE_HOURS }} hours old are eligible. - - - Gradle: ${{ steps.update.outputs.gradle_line }} - - Maven: ${{ steps.update.outputs.maven_line }} - - Maven Surefire: ${{ steps.update.outputs.surefire_line }} - - # Motivation - - Keep smoke tests running against the latest eligible stable versions of build tools without adopting releases in their first 48 hours. - - # Contributor Checklist - - - [ ] Verify smoke tests pass with the new versions - EOF - )" diff --git a/dd-java-agent/instrumentation/kafka/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaProducerInstrumentation.java b/dd-java-agent/instrumentation/kafka/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaProducerInstrumentation.java index 1887e0a5205..40aecbdac09 100644 --- a/dd-java-agent/instrumentation/kafka/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaProducerInstrumentation.java +++ b/dd-java-agent/instrumentation/kafka/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaProducerInstrumentation.java @@ -46,6 +46,7 @@ import datadog.trace.instrumentation.kafka_common.ClusterIdHolder; import datadog.trace.instrumentation.kafka_common.KafkaConfigHelper; import datadog.trace.instrumentation.kafka_common.MetadataState; +import datadog.trace.instrumentation.kafka_common.Utils; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.matcher.ElementMatcher; @@ -219,7 +220,7 @@ public static void onEnter( } DataStreamsTags tags = createWithClusterId("kafka", OUTBOUND, record.topic(), clusterId); try { - defaultPropagator().inject(span, record.headers(), setter); + defaultPropagator().inject(Utils.currentContext(), record.headers(), setter); if (STREAMING_CONTEXT.isDisabledForTopic(record.topic()) || STREAMING_CONTEXT.isSinkTopic(record.topic())) { // inject the context in the headers, but delay sending the stats until we know the @@ -241,7 +242,7 @@ record = record.value(), record.headers()); - defaultPropagator().inject(span, record.headers(), setter); + defaultPropagator().inject(Utils.currentContext(), record.headers(), setter); if (STREAMING_CONTEXT.isDisabledForTopic(record.topic()) || STREAMING_CONTEXT.isSinkTopic(record.topic())) { Propagator dsmPropagator = Propagators.forConcern(DSM_CONCERN); diff --git a/dd-java-agent/instrumentation/kafka/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/ProducerContextPropagationAdvice.java b/dd-java-agent/instrumentation/kafka/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/ProducerContextPropagationAdvice.java index 0ca9823d92e..3175dd7c397 100644 --- a/dd-java-agent/instrumentation/kafka/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/ProducerContextPropagationAdvice.java +++ b/dd-java-agent/instrumentation/kafka/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/ProducerContextPropagationAdvice.java @@ -19,6 +19,7 @@ import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.instrumentation.kafka_common.MetadataState; +import datadog.trace.instrumentation.kafka_common.Utils; import net.bytebuddy.asm.Advice; import org.apache.kafka.clients.Metadata; import org.apache.kafka.clients.producer.ProducerRecord; @@ -43,7 +44,7 @@ public static void onEnter( } DataStreamsTags tags = create("kafka", OUTBOUND, record.topic(), null, clusterId); try { - defaultPropagator().inject(span, record.headers(), setter); + defaultPropagator().inject(Utils.currentContext(), record.headers(), setter); if (STREAMING_CONTEXT.isDisabledForTopic(record.topic()) || STREAMING_CONTEXT.isSinkTopic(record.topic())) { // inject the context in the headers, but delay sending the stats until we know the @@ -65,7 +66,7 @@ record = record.value(), record.headers()); - defaultPropagator().inject(span, record.headers(), setter); + defaultPropagator().inject(Utils.currentContext(), record.headers(), setter); if (STREAMING_CONTEXT.isDisabledForTopic(record.topic()) || STREAMING_CONTEXT.isSinkTopic(record.topic())) { Propagator dsmPropagator = Propagators.forConcern(DSM_CONCERN); diff --git a/dd-java-agent/instrumentation/kafka/kafka-common/src/main/java/datadog/trace/instrumentation/kafka_common/Utils.java b/dd-java-agent/instrumentation/kafka/kafka-common/src/main/java/datadog/trace/instrumentation/kafka_common/Utils.java index d0f7eb4fcea..58a8cefe82a 100644 --- a/dd-java-agent/instrumentation/kafka/kafka-common/src/main/java/datadog/trace/instrumentation/kafka_common/Utils.java +++ b/dd-java-agent/instrumentation/kafka/kafka-common/src/main/java/datadog/trace/instrumentation/kafka_common/Utils.java @@ -1,5 +1,6 @@ package datadog.trace.instrumentation.kafka_common; +import datadog.context.Context; import datadog.trace.api.datastreams.DataStreamsTransactionTracker; import java.nio.charset.StandardCharsets; import org.apache.kafka.clients.consumer.ConsumerRecord; @@ -9,6 +10,11 @@ public final class Utils { private Utils() {} // prevent instantiation + /** Returns the current context from the thread-local context store. */ + public static Context currentContext() { + return Context.current(); + } + public static DataStreamsTransactionTracker.TransactionSourceReader DSM_TRANSACTION_SOURCE_READER = (source, headerName) -> {