From 03dd528fde8bc59d15b6901b9763e32839db3304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Thu, 2 Apr 2026 17:34:57 +0200 Subject: [PATCH 1/6] ci: Restrict release workflow to master branch builds Previously, the release workflow triggered on every "Build and test" run regardless of branch. Although a job-level condition prevented actual releases, the workflow still ran and prompted admin approval due to its access to signing and publishing secrets. Added a branches filter to the workflow_run trigger so the workflow is never queued for feature branch builds, and removed the now-redundant head_branch check from the job condition. --- .github/workflows/release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b5323ba9..84d90076 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,6 +5,8 @@ on: workflows: ["Build and test"] types: - completed + branches: + - master workflow_dispatch: inputs: dry_run: @@ -23,7 +25,7 @@ jobs: contents: write issues: write pull-requests: write - if: github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'master') + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') steps: - uses: actions/checkout@v5 with: From b177456cb7a6428c5921d8592fc2a649f626d002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Thu, 2 Apr 2026 17:42:28 +0200 Subject: [PATCH 2/6] ci: Check out the exact commit that passed CI for releases When triggered by workflow_run, actions/checkout defaults to the HEAD of the default branch at the time the workflow starts, not the commit that triggered the parent workflow. This creates a race window where a commit that hasn't been tested could be released if new commits land on master between CI completing and the release workflow starting. Pin the checkout to github.event.workflow_run.head_sha when triggered by workflow_run so the release always runs against the tested commit. The ref is left empty for workflow_dispatch, preserving the default behavior of checking out the dispatched ref. --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 84d90076..cdff8b94 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,6 +30,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false + ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || '' }} - uses: actions/setup-java@v5 with: java-version: "21" From 05ba2629c5ef3b9daa18a0acef33d8ecd62e3c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Thu, 2 Apr 2026 19:36:45 +0200 Subject: [PATCH 3/6] chore(ci): bump GitHub Actions major versions Updated GitHub Actions to their latest major versions across all workflows to keep the CI environment up-to-date and secure: - actions/checkout to v6 - actions/setup-java to v5 - actions/upload-artifact to v6 - actions/download-artifact to v8 - gradle/actions/setup-gradle to v5 Configuration parameters remain compatible with the new versions. --- .github/workflows/build-and-test.yml | 20 ++++++++++---------- .github/workflows/release.yml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 85764bbf..baab71d2 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -17,14 +17,14 @@ jobs: name: Build and check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-java@v5 with: java-version: '21' distribution: 'temurin' - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Generate and submit dependency graph uses: gradle/actions/dependency-submission@v4 @@ -34,7 +34,7 @@ jobs: run: ./gradlew shadowJar annotation:jar check integrationTest - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: Jars path: | @@ -61,9 +61,9 @@ jobs: name: Run test suite with Java ${{ matrix.java }} needs: build-and-check steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 name: Set up Java with: java-version: ${{ matrix.java }} @@ -83,7 +83,7 @@ jobs: - uses: sbt/setup-sbt@v1 - name: Download artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: Jars @@ -95,21 +95,21 @@ jobs: working-directory: ./agent run: bin/test_projects - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 name: Set up Gradle cache with: java-version: ${{ matrix.java }} distribution: 'temurin' cache: gradle - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 name: Set up Maven cache with: java-version: ${{ matrix.java }} distribution: 'temurin' cache: maven - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 name: Set up sbt cache with: java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cdff8b94..44744c65 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ jobs: pull-requests: write if: github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: persist-credentials: false ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || '' }} From 87556e26afac4dfa0080e2f8d12131fff3a5b6f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Thu, 2 Apr 2026 18:20:07 +0200 Subject: [PATCH 4/6] test: Remove Jackson dependency from petclinic fixture The upstream spring-framework-petclinic project changed Jackson coordinates from com.fasterxml.jackson to tools.jackson.core, breaking our custom ShowAvailable controller in petclinic-fw tests. Replaced ObjectMapper with manual JSON formatting and removed the now-unused Result inner class, making the test fixture resilient to upstream dependency changes. --- .../samples/petclinic/web/ShowAvailable.java | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/agent/src/test/fixture/shared/src/main/java/org/springframework/samples/petclinic/web/ShowAvailable.java b/agent/src/test/fixture/shared/src/main/java/org/springframework/samples/petclinic/web/ShowAvailable.java index 65f002e3..e1b6d36d 100644 --- a/agent/src/test/fixture/shared/src/main/java/org/springframework/samples/petclinic/web/ShowAvailable.java +++ b/agent/src/test/fixture/shared/src/main/java/org/springframework/samples/petclinic/web/ShowAvailable.java @@ -1,34 +1,19 @@ package org.springframework.samples.petclinic.web; -import java.io.IOException; - import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * ShowAvailable is a simple Spring Controller that simply returns the number * of bytes available in the request's InputStream. */ @RestController public class ShowAvailable { - private static class Result { - private final int available; - - public Result(int available) { - this.available = available; - } - - public String getAvailable() { - return Integer.toString(available); - } - } @PostMapping("/showavailable") - public String doPost(@RequestBody String body) throws Exception { - return new ObjectMapper().writeValueAsString(new Result(body.length())); + public String doPost(@RequestBody String body) { + return String.format("{\"available\":\"%d\"}", body.length()); } } From 99d47838239059a3883cdcd30c995cc9a2e74300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Thu, 2 Apr 2026 18:51:31 +0200 Subject: [PATCH 5/6] test: Skip intellij tests on java 17 Upstream now requires Java 21. --- agent/test/intellij/intellij.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/test/intellij/intellij.bats b/agent/test/intellij/intellij.bats index 35f497f5..4b864363 100755 --- a/agent/test/intellij/intellij.bats +++ b/agent/test/intellij/intellij.bats @@ -5,7 +5,7 @@ init_plugin() { } setup_file() { - is_java 17 || skip "needs Java 17" + is_java 21 || skip "needs Java 21" is_java 25 && skip "incompatible with Java 25" export AGENT_JAR="$(find_agent_jar)" From 6dd4744a7e4b0a29a3a2b03c8225d8e0668c6cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Thu, 2 Apr 2026 19:17:42 +0200 Subject: [PATCH 6/6] test: Fix petclinic fixture method rename and log level changes The upstream spring-petclinic project renamed the `testOwnerDetails` test method to `ownerDetails` and changed the log level of some statements from INFO to DEBUG. - Updated `petclinic-tests.bats` to support both test method names by using wildcards/regex. - Expanded the log label assertion to match both `info` and `debug` functions. - Wrapped the jq log label extraction in `first()` to prevent multiple matches from causing the `assert_json_eq` to fail with multiple lines. --- agent/test/petclinic/petclinic-tests.bats | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/agent/test/petclinic/petclinic-tests.bats b/agent/test/petclinic/petclinic-tests.bats index c7c6f7ab..513cc3a6 100644 --- a/agent/test/petclinic/petclinic-tests.bats +++ b/agent/test/petclinic/petclinic-tests.bats @@ -40,13 +40,13 @@ run_petclinic_test() { @test "hooked functions are ordered correctly" { run_petclinic_test assert_success - run cat ./tmp/appmap/junit/org_springframework_samples_petclinic_${TEST_NAME}_testOwnerDetails.appmap.json + run cat ./tmp/appmap/junit/org_springframework_samples_petclinic_${TEST_NAME}_*wnerDetails.appmap.json assert_success # Find the test runner's main thread (the one with testOwnerDetails method). # Check to make sure that parent_id of the "return" event matches the id of the "call" event. # Note: In Java 21 the main thread is typically thread 1, but in Java 25 it can be thread 3. - local main_thread_id=$(jq -r '[.events[] | select(.method_id == "testOwnerDetails")][0].thread_id' ./tmp/appmap/junit/org_springframework_samples_petclinic_${TEST_NAME}_testOwnerDetails.appmap.json) + local main_thread_id=$(jq -r '[.events[] | select(.method_id | test("^.*wnerDetails$")?)][0].thread_id' ./tmp/appmap/junit/org_springframework_samples_petclinic_${TEST_NAME}_*wnerDetails.appmap.json) assert_json_eq ".events | map(select(.thread_id == ${main_thread_id})) | ((.[0].event == \"call\" and .[1].event == \"return\") and (.[1].parent_id == .[0].id))" "true" } @@ -62,9 +62,9 @@ run_petclinic_test() { @test "log methods are labeled" { run_petclinic_test "${TEST_NAME}" appmap-labels.yml assert_success - run cat ./tmp/appmap/junit/org_springframework_samples_petclinic_${TEST_NAME}_testOwnerDetails.appmap.json + run cat ./tmp/appmap/junit/org_springframework_samples_petclinic_${TEST_NAME}_*wnerDetails.appmap.json - assert_json_eq '.classMap[0] | recurse(.children[]?) | select(.type? == "function" and .name? == "info").labels[0]' 'log' + assert_json_eq 'first(.classMap[0] | recurse(.children[]?) | select(.type? == "function" and (.name? | IN("info", "debug")))).labels[0]' 'log' } @test "test_status set for successful test" {