From 6d9c990e2a4e2f899b050935186cbf8d4f1dbb06 Mon Sep 17 00:00:00 2001 From: Florian Dreier Date: Wed, 19 Aug 2026 14:12:49 +0200 Subject: [PATCH] TS-47496 Keep the executable flags in the distribution archives Archive tasks are reproducible by default since Gradle 9, which packages every file with fixed permissions of 644 instead of taking them from the file system. The upgrade in 36.0.0 therefore stripped the executable flag from installer.sh and from the launchers and native binaries of the installer's Linux runtime image, so the profiler could not be installed from the zip without a chmod first. Only bin/convert kept its flag, because the application plugin sets the permissions of the bin directory explicitly rather than relying on the file system. The distribution archives now opt out of that part of reproducibility again via useFileSystemPermissions(); the fixed file order and timestamps stay in place, and permissions set explicitly still win. Comparing the rebuilt zip against 35.2.1, the last release built with Gradle 8, shows the same set of executables again, up to the JDK's own binaries changing between the two runtime versions. VerifyExecutablePermissions guards the entries that have to stay executable and runs as part of check. It is skipped on Windows, which has no executable flag to preserve; the released distribution is built on Linux. Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 1 + agent/build.gradle.kts | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b84e29892..dc8b99dcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ We use [semantic versioning](http://semver.org/): - [breaking] _agent_: Log lines now show the simple class name (`INFO Agent - ...`) instead of the fully qualified one. - [breaking] _agent_: In testwise coverage mode, the test result is now mandatory in the body of `/test/end` requests. Requests without a result (or without a body at all) are rejected with "400 Bad Request" instead of silently producing a report entry without a result. The duration remains optional: if it is omitted, the profiler derives it from the time between the `/test/start` and `/test/end` requests. The profiler additionally logs a warning if no `/test/start` request was received, since the duration cannot be derived reliably in that case. - [breaking] _tia-client_: Removed the `ITestwiseCoverageAgentApi.testFinished(testUniformPath)` overload, which sent a `/test/end` request without a body. Since the agent now rejects such requests, use `testFinished(testUniformPath, testExecution)` instead. +- [fix] _agent_: The files in `teamscale-jacoco-agent.zip` are packaged with their executable flag again. Since version 36.0.0 `installer.sh` and the binaries of the bundled installer runtime were extracted without it, so installing the profiler on Linux required a `chmod +x` first. - [fix] _agent_: A test whose result the profiler does not know is now reported as `INCONCLUSIVE` instead of `SKIPPED`. This affects tests that are ended implicitly because the next `/test/start` arrived before their `/test/end`, or because the test run ended while the tests were still running. - [fix] _agent_: Requests to the profiler's REST API that are rejected as invalid (e.g. a `/test/start` without a test name or an empty `PUT /partition` body) now respond with the appropriate HTTP status code, e.g. "400 Bad Request". diff --git a/agent/build.gradle.kts b/agent/build.gradle.kts index 3cf24b7db..c1334a8d9 100644 --- a/agent/build.gradle.kts +++ b/agent/build.gradle.kts @@ -134,6 +134,7 @@ verifyShadowedLoggingConfigs(tasks.shadowJar, tasks.shadowDistZip) tasks.shadowDistZip { archiveFileName = "teamscale-jacoco-agent.zip" + useFileSystemPermissions() } oci {