diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cebd8993d..7efc2bc52 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,29 +36,46 @@ jobs: run: ./gradlew build -x test test: - name: test (${{ matrix.test-java-version }}) - runs-on: ubuntu-latest + name: Test + runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: + os: + - macos-latest + - macos-13 + - ubuntu-latest + - windows-latest test-java-version: - 8 - 11 - 17 - 21 - 23 - fail-fast: false + # macos-latest drops support for java 8 temurin. Run java 8 on macos-13. Run java 11, 17, 21 on macos-latest. + exclude: + - os: macos-latest + test-java-version: 8 + - os: macos-13 + test-java-version: 11 + - os: macos-13 + test-java-version: 17 + - os: macos-13 + test-java-version: 21 + - os: macos-13 + test-java-version: 23 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - id: setup-test-java - name: Set up JDK ${{ matrix.test-java-version }} for running tests + - id: setup-java-test + name: Set up Java ${{ matrix.test-java-version }} for tests uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: - # using zulu because new releases get published quickly - distribution: zulu + distribution: temurin java-version: ${{ matrix.test-java-version }} - - name: Set up JDK for running Gradle + - id: setup-java + name: Set up Java for build uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: temurin @@ -71,9 +88,9 @@ jobs: - name: Gradle test run: > ./gradlew test - -PtestJavaVersion=${{ matrix.test-java-version }} - -Porg.gradle.java.installations.paths=${{ steps.setup-test-java.outputs.path }} - -Porg.gradle.java.installations.auto-download=false + "-PtestJavaVersion=${{ matrix.test-java-version }}" + "-Porg.gradle.java.installations.paths=${{ steps.setup-java-test.outputs.path }}" + "-Porg.gradle.java.installations.auto-download=false" integration-test: runs-on: ubuntu-latest diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManager.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManager.java index 0f3ad7ad7..1f76419ab 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManager.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManager.java @@ -11,13 +11,14 @@ import io.opentelemetry.contrib.disk.buffering.internal.storage.files.ReadableFile; import io.opentelemetry.contrib.disk.buffering.internal.storage.files.WritableFile; import io.opentelemetry.sdk.common.Clock; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.Objects; import javax.annotation.Nullable; import org.jetbrains.annotations.NotNull; -public final class FolderManager { +public final class FolderManager implements Closeable { private final File folder; private final Clock clock; private final StorageConfiguration configuration; @@ -30,6 +31,16 @@ public FolderManager(File folder, StorageConfiguration configuration, Clock cloc this.clock = clock; } + @Override + public void close() throws IOException { + if (currentReadableFile != null) { + currentReadableFile.close(); + } + if (currentWritableFile != null) { + currentWritableFile.close(); + } + } + @Nullable public synchronized ReadableFile getReadableFile() throws IOException { currentReadableFile = null; diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java index b2da05c24..b46cba12f 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java @@ -48,6 +48,7 @@ import java.util.function.Function; import java.util.function.Supplier; import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -103,6 +104,11 @@ void setUp() throws IOException { logger = createLoggerProvider(logToDiskExporter).get("LogInstrumentationScope"); } + @AfterEach + void tearDown() throws IOException { + spanStorage.close(); + } + @NotNull private ToDiskExporter buildToDiskExporter( SignalSerializer serializer, Function, CompletableResultCode> exporter) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java index 0d9e16723..f5b72496a 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -40,6 +41,11 @@ void setUp() { folderManager = new FolderManager(rootDir, TestData.getDefaultConfiguration(rootDir), clock); } + @AfterEach + void tearDown() throws Exception { + folderManager.close(); + } + @Test void createWritableFile_withTimeMillisAsName() throws IOException { when(clock.now()).thenReturn(MILLISECONDS.toNanos(1000L)); diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java index 9accaefff..7f134afdc 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.IOException; import java.util.function.Function; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -47,6 +48,11 @@ void setUp() throws IOException { storage = new Storage(folderManager, true); } + @AfterEach + void tearDown() throws IOException { + storage.close(); + } + @Test void whenReadingAndProcessingSuccessfully_returnSuccess() throws IOException { when(folderManager.getReadableFile()).thenReturn(readableFile); diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java index dd8cb02aa..b54deb7e9 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -104,6 +105,11 @@ void setUp() throws IOException { source, CREATED_TIME_MILLIS, clock, getConfiguration(temporaryFileProvider, dir)); } + @AfterEach + void tearDown() throws IOException { + readableFile.close(); + } + private static void addFileContents(File source) throws IOException { List items = new ArrayList<>(); items.add(SERIALIZER.serialize(Collections.singleton(FIRST_LOG_RECORD))); diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java index 8ff749c1e..7d3ea3757 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java @@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.List; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -47,6 +48,11 @@ void setUp() throws IOException { clock); } + @AfterEach + void tearDown() throws IOException { + writableFile.close(); + } + @Test void hasNotExpired_whenWriteAgeHasNotExpired() { when(clock.now()).thenReturn(MILLISECONDS.toNanos(1500L)); diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java index 1b6a7e3e2..76a6333ba 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java @@ -7,6 +7,7 @@ import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.condition.OS.WINDOWS; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; @@ -31,9 +32,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.io.TempDir; +@DisabledOnOs(WINDOWS) // Uses async-profiler, which is not supported on Windows public class InferredSpansAutoConfigTest { @BeforeEach @@ -107,7 +108,6 @@ public void checkDisabledbyDefault() { } @DisabledOnOpenJ9 - @DisabledOnOs(OS.WINDOWS) @Test public void checkProfilerWorking() { try (AutoConfigTestProperties props = diff --git a/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java b/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java index 2d3178072..b51144360 100644 --- a/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java +++ b/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java @@ -17,6 +17,8 @@ import java.util.List; import java.util.Properties; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; import org.junitpioneer.jupiter.ClearSystemProperty; class JmxScraperTest { @@ -46,8 +48,10 @@ private static void testInvalidArguments(String... args) { } @Test + @DisabledOnOs(OS.WINDOWS) void shouldCreateConfig_propertiesLoadedFromFile() throws InvalidArgumentException { // Given + // Windows returns /C:/path/to/file, which is not a valid path for Path.get() in Java. String filePath = ClassLoader.getSystemClassLoader().getResource("validConfig.properties").getPath(); List args = Arrays.asList("-config", filePath); diff --git a/opamp-client/build.gradle.kts b/opamp-client/build.gradle.kts index a1f0c698e..5b4b5bf7e 100644 --- a/opamp-client/build.gradle.kts +++ b/opamp-client/build.gradle.kts @@ -1,6 +1,6 @@ -import de.undercouch.gradle.tasks.download.Download import de.undercouch.gradle.tasks.download.DownloadExtension -import groovy.json.JsonSlurper +import java.net.HttpURLConnection +import java.net.URL plugins { id("otel.java-conventions") @@ -16,19 +16,9 @@ dependencies { compileOnly("com.google.auto.value:auto-value-annotations") } -val opampReleaseInfo = tasks.register("opampLastReleaseInfo") { - group = "opamp" - src("https://api.github.com/repos/open-telemetry/opamp-spec/releases/latest") - dest(project.layout.buildDirectory.file("opamp/release.json")) -} - val opampProtos = tasks.register("opampProtoDownload", download) opampProtos.configure { group = "opamp" - dependsOn(opampReleaseInfo) - lastReleaseInfoJson.set { - opampReleaseInfo.get().dest - } outputProtosDir.set(project.layout.buildDirectory.dir("opamp/protos")) downloadedZipFile.set(project.layout.buildDirectory.file("intermediate/$name/release.zip")) } @@ -46,20 +36,28 @@ abstract class DownloadOpampProtos @Inject constructor( private val fileOps: FileSystemOperations, ) : DefaultTask() { - @get:InputFile - abstract val lastReleaseInfoJson: RegularFileProperty - @get:OutputDirectory abstract val outputProtosDir: DirectoryProperty @get:Internal abstract val downloadedZipFile: RegularFileProperty - @Suppress("UNCHECKED_CAST") @TaskAction fun execute() { - val releaseInfo = JsonSlurper().parse(lastReleaseInfoJson.get().asFile) as Map - val zipUrl = releaseInfo["zipball_url"] + // Get the latest release tag by following the redirect from GitHub's latest release URL + val latestReleaseUrl = "https://github.com/open-telemetry/opamp-spec/releases/latest" + val connection = URL(latestReleaseUrl).openConnection() as HttpURLConnection + connection.instanceFollowRedirects = false + connection.requestMethod = "HEAD" + + val redirectLocation = connection.getHeaderField("Location") + connection.disconnect() + + // Extract tag from URL like: https://github.com/open-telemetry/opamp-spec/releases/tag/v0.12.0 + val latestTag = redirectLocation.substringAfterLast("/") + // Download the source code for the latest release + val zipUrl = "https://github.com/open-telemetry/opamp-spec/zipball/$latestTag" + download.run { src(zipUrl) dest(downloadedZipFile)