From b5f15aa993ca0c18ced219bcd5744c2df5eb1879 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Thu, 30 Apr 2026 13:15:19 -0700 Subject: [PATCH 1/2] Stop using `pull_request: labeled` to gate optional tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The labeled trigger caused two issues that combined into recurring CI breakage on PRs that received any label (renovate, dependabot, code-review-sweep, the labeler, or a human applied one): * GitHub evaluates a workflow's `concurrency:` group before its job-level `if:` filter, so a labeled run cancelled the in-progress real build before being filtered out. * Even after a conditional concurrency-group fix, the labeled run's check_suite displaced the in-progress real build's check_suite in the PR Checks UI (GitHub keys that view by workflow file, latest check_suite wins). Concrete failure: PR #18441, run https://github.com/open-telemetry/opentelemetry-java-instrumentation/actions/runs/25156724872 — every job ended within ~2 seconds with no steps executed. Fix: drop `labeled` from the trigger entirely. Read labels from `github.event.pull_request.labels` (which is present on every `pull_request` event) and gate optional jobs by `contains(...)`. Skipped jobs that are listed as required satisfy branch protection, so auto-merge still works. * `test openj9` / `test windows` labels: still consulted, but only at the moments the build naturally runs (opened / synchronize / reopened). Applying a label after the last push no longer re-triggers the build; to pick up the label, close/reopen the PR or push another commit. This trade-off avoids the labeled-event race and the wasted reruns from non-test labels. * `test native` is now detected inline from the PR's changed paths via a new `resolve-native` job that mirrors the former `.github/labeler.yml` `test native` rule. The label is no longer auto-applied; the manual label is still honored as a force-enable. * `.github/labeler.yml` and `.github/workflows/label.yml` are deleted (the labeler's only rule was the `test native` one). --- .github/labeler.yml | 11 ---- .github/workflows/build-pull-request.yml | 66 ++++++++++++++++----- .github/workflows/comment-on-test-label.yml | 34 +++++++++++ .github/workflows/label.yml | 20 ------- 4 files changed, 85 insertions(+), 46 deletions(-) delete mode 100644 .github/labeler.yml create mode 100644 .github/workflows/comment-on-test-label.yml delete mode 100644 .github/workflows/label.yml diff --git a/.github/labeler.yml b/.github/labeler.yml deleted file mode 100644 index 342f4cc2889a..000000000000 --- a/.github/labeler.yml +++ /dev/null @@ -1,11 +0,0 @@ -test native: -- all: - - changed-files: - - any-glob-to-any-file: - - instrumentation/logback/logback-appender-1.0/library/** - - instrumentation/jdbc/library/** - - instrumentation/spring/** - - smoke-tests-otel-starter/** - - dependencyManagement/build.gradle.kts - - settings.gradle.kts - - all-globs-to-all-files: '!instrumentation/spring/**/javaagent/**' diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index c243d6c3cfea..103490a1a88b 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -1,12 +1,26 @@ name: Build pull request +# Optional test variants (openj9, windows) are gated by `test openj9` / +# `test windows` labels on the PR, read from the event payload. We +# deliberately do NOT subscribe to `pull_request: [labeled]` — see the +# description of PR #18446 for the history of why every previous attempt +# to use that trigger failed. +# +# Practical consequence: adding a `test openj9` / `test windows` label +# doesn't retrigger the build. Push another commit or close/reopen the +# PR to pick it up. `comment-on-test-label.yml` posts a reminder when +# one of those labels is added. +# +# `test native` is detected automatically from the PR's changed paths +# (the `resolve-native` job below). The manual `test native` label is +# still honored as a force-enable. + on: pull_request: types: - opened - synchronize - reopened - - labeled concurrency: group: build-pull-request-${{ github.event.pull_request.number }} @@ -16,22 +30,44 @@ permissions: contents: read jobs: + # Run native tests automatically when the PR touches a library + # instrumentation module with native support (logback-appender, jdbc, + # spring), the native smoke test harness, or the top-level build config + # that affects them. + resolve-native: + runs-on: ubuntu-latest + outputs: + run-native-tests: ${{ steps.filter.outputs.native }} + steps: + - name: Detect native-relevant changes + id: filter + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + # `|| true` so an empty result from `grep -v` (everything filtered) + # doesn't fail the step under pipefail. + files=$( + gh api --paginate "/repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/files" \ + --jq '.[].filename' | + grep -Ev '^instrumentation/spring/.+/javaagent/' || true + ) + include='^instrumentation/logback/logback-appender-1\.0/library/' + include+='|^instrumentation/jdbc/library/' + include+='|^instrumentation/spring/' + include+='|^smoke-tests-otel-starter/' + include+='|^dependencyManagement/build\.gradle\.kts$' + include+='|^settings\.gradle\.kts$' + if grep -Eq "$include" <<<"$files"; then + echo "native=true" >> "$GITHUB_OUTPUT" + else + echo "native=false" >> "$GITHUB_OUTPUT" + fi + build: - # On `labeled` events, only proceed when the added label affects what we - # build. All other event types (opened, synchronize, reopened) always - # proceed. - if: | - github.event.action != 'labeled' || - github.event.label.name == 'test native' || - github.event.label.name == 'test openj9' || - github.event.label.name == 'test windows' + needs: [resolve-native] uses: ./.github/workflows/reusable-pr-build.yml with: - # it's rare for only the openj9 tests, openj9 smoke variants, the windows - # smoke tests, or the native tests to break, so they are gated by labels. - # `test native` is applied automatically by .github/labeler.yml when the - # PR diff touches native-relevant paths; `test openj9` and `test windows` - # are applied manually. - skip-native-tests: ${{ !contains(github.event.pull_request.labels.*.name, 'test native') }} + skip-native-tests: ${{ !(needs.resolve-native.outputs.run-native-tests == 'true' || contains(github.event.pull_request.labels.*.name, 'test native')) }} 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') }} diff --git a/.github/workflows/comment-on-test-label.yml b/.github/workflows/comment-on-test-label.yml new file mode 100644 index 000000000000..911908bfd607 --- /dev/null +++ b/.github/workflows/comment-on-test-label.yml @@ -0,0 +1,34 @@ +name: Comment on test-* label + +# Posts a reminder when a `test openj9` / `test windows` label is added, +# explaining that `build-pull-request.yml` doesn't retrigger on `labeled` +# events (see the design notes at the top of that file for the rationale). +# Without this, applying the label and waiting would look broken. +# +# Why `pull_request_target` is safe here: this workflow does NOT check out +# or execute any PR code. Its only step is `gh pr comment`. Fork PRs +# therefore can't influence what runs, so the secrets that +# `pull_request_target` would normally expose are not reachable. + +on: + pull_request_target: + types: [labeled] + +permissions: + contents: read + pull-requests: write + +jobs: + comment: + if: | + github.event.label.name == 'test openj9' || + github.event.label.name == 'test windows' + runs-on: ubuntu-latest + steps: + - name: Post explanatory comment + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + LABEL: ${{ github.event.label.name }} + run: | + gh pr comment "$PR_NUMBER" --body "The \`$LABEL\` label has been added, but the build only consults test-* labels at the moments it naturally runs (PR opened / synchronize / reopened). To pick up this label, push another commit or close-and-reopen the PR." diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml deleted file mode 100644 index 38e513bac9e5..000000000000 --- a/.github/workflows/label.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Labeler -on: [pull_request_target] - -permissions: - contents: read - -jobs: - label: - runs-on: ubuntu-latest - steps: - - uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 - id: otelbot-token - with: - app-id: ${{ vars.OTELBOT_JAVA_INSTRUMENTATION_APP_ID }} - private-key: ${{ secrets.OTELBOT_JAVA_INSTRUMENTATION_PRIVATE_KEY }} - - - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 - with: - # Not using GITHUB_TOKEN since labels from that token do not trigger workflows. - repo-token: "${{ steps.otelbot-token.outputs.token }}" From 682c90c3d173825ec10d632425a8a67825f8dd61 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Thu, 30 Apr 2026 20:14:49 -0700 Subject: [PATCH 2/2] comment --- .github/workflows/build-pull-request.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 103490a1a88b..a0b681d1c7bc 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -2,9 +2,9 @@ name: Build pull request # Optional test variants (openj9, windows) are gated by `test openj9` / # `test windows` labels on the PR, read from the event payload. We -# deliberately do NOT subscribe to `pull_request: [labeled]` — see the -# description of PR #18446 for the history of why every previous attempt -# to use that trigger failed. +# deliberately do NOT subscribe to `pull_request: [labeled]` — see +# https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/18446 +# for the history of why every previous attempt to use that trigger failed. # # Practical consequence: adding a `test openj9` / `test windows` label # doesn't retrigger the build. Push another commit or close/reopen the