-
Notifications
You must be signed in to change notification settings - Fork 35
Add native OSGi bundle metadata to published jars #498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
6a07130
Add native OSGi bundle metadata to published jars
royteeuwen ea02984
Add OSGi integration test that resolves semconv bundles in Felix
royteeuwen f297d0a
Simplify OSGi config: apply unconditionally, drop osgiEnabled/osgiOpt…
royteeuwen 4b59915
Pin io.opentelemetry.api.* OSGi import to [1.33,2) range
royteeuwen b05fd8c
Derive OSGi api import range from a shared baseline constant
royteeuwen eb107e2
Merge branch 'main' into osgi-support
trask File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
buildSrc/src/main/kotlin/io/opentelemetry/gradle/OtelVersions.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.gradle | ||
|
|
||
| /** Shared version constants used across build scripts and convention plugins. */ | ||
| object OtelVersions { | ||
| /** | ||
| * The minimum opentelemetry-api version the semconv modules are built against. It is the | ||
| * compileOnly baseline pinned in :dependencyManagement and the lower bound of the OSGi | ||
| * Import-Package range emitted for io.opentelemetry.api.* by otel.java-conventions. Keep it as | ||
| * the single source of truth for both. | ||
| */ | ||
| const val OTEL_API_BASELINE = "1.33.0" | ||
|
|
||
| /** | ||
| * OSGi version range for io.opentelemetry.api.* imports: the baseline up to (but excluding) the | ||
| * next major, e.g. "[1.33,2)". bnd can't infer this itself because the pinned opentelemetry-api | ||
| * baseline isn't a bnd bundle, so we set it explicitly. | ||
| */ | ||
| val OTEL_API_OSGI_RANGE: String | ||
| get() { | ||
| val floor = OTEL_API_BASELINE.substringBeforeLast('.') // e.g. 1.33 | ||
| val nextMajor = OTEL_API_BASELINE.substringBefore('.').toInt() + 1 // e.g. 2 | ||
| return "[$floor,$nextMajor)" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| import aQute.bnd.gradle.Bundle | ||
| import aQute.bnd.gradle.Resolve | ||
| import aQute.bnd.gradle.TestOSGi | ||
|
|
||
| plugins { | ||
| id("otel.java-conventions") | ||
| } | ||
|
|
||
| description = "OpenTelemetry Semantic Conventions OSGi Integration Tests" | ||
| otelJava.moduleName.set("io.opentelemetry.semconv.integration.tests.osgi") | ||
|
|
||
| // The semconv bundles Import-Package io.opentelemetry.api.common, so resolution needs an | ||
| // opentelemetry-api that is itself a proper OSGi bundle. OSGi metadata was added to the core | ||
| // artifacts in opentelemetry-java#8417, well after the 1.33.0 compileOnly baseline pinned in | ||
| // :dependencyManagement, so we force a recent version on this test module's classpath only. | ||
| val osgiOtelApiVersion = "1.63.0" | ||
|
|
||
| configurations.configureEach { | ||
| resolutionStrategy { | ||
| force("io.opentelemetry:opentelemetry-api:$osgiOtelApiVersion") | ||
| } | ||
| } | ||
|
|
||
| dependencies { | ||
| testImplementation(project(":semconv")) | ||
| testImplementation(project(":semconv-incubating")) | ||
| // Provides the io.opentelemetry.api.* packages the semconv bundles import, as an OSGi bundle. | ||
| testImplementation("io.opentelemetry:opentelemetry-api:$osgiOtelApiVersion") | ||
|
|
||
| testImplementation("org.osgi:org.osgi.test.junit5:1.3.0") | ||
| // Provided by the OSGi framework at runtime. | ||
| testCompileOnly("org.osgi:osgi.core:8.0.0") | ||
|
|
||
| testRuntimeOnly("org.junit.platform:junit-platform-launcher") | ||
| testRuntimeOnly("org.apache.felix:org.apache.felix.framework:7.0.5") | ||
| // opentelemetry-common (pulled in transitively by opentelemetry-api) declares | ||
| // Require-Capability: osgi.extender=osgi.serviceloader.processor, so the container needs Aries | ||
| // SPI Fly to resolve even though semconv itself has no ServiceLoader providers. | ||
| testRuntimeOnly("org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle:1.3.7") | ||
| } | ||
|
|
||
| // The testing bundle (our JUnit tests + Test-Cases header) is booted inside a real Felix container | ||
| // via bnd's Bundle -> Resolve -> TestOSGi task chain, modeled on opentelemetry-java's | ||
| // integration-tests/osgi module. | ||
| val bsn = "opentelemetry-semconv-osgi-testing" | ||
| val runee = "JavaSE-${java.toolchain.languageVersion.get()}" | ||
| val testRuntimeClasspath = sourceSets.test.get().runtimeClasspath | ||
|
|
||
| val testingBundle = tasks.register<Bundle>("testingBundle") { | ||
| archiveClassifier.set("testing") | ||
| from(sourceSets.test.get().output) | ||
| bundle { | ||
| // BND analyses compileClasspath by default; use the runtime classpath so testImplementation | ||
| // deps (junit-jupiter, assertj) are visible and Test-Cases gets populated. | ||
| classpath(testRuntimeClasspath) | ||
| bnd( | ||
| "Bundle-SymbolicName: $bsn", | ||
| "Test-Cases: \${classes;HIERARCHY_INDIRECTLY_ANNOTATED;org.junit.platform.commons.annotation.Testable;CONCRETE}", | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| val inputBndrun = layout.buildDirectory.file("bndrun/test.bndrun") | ||
| val generateBndrun = tasks.register("generateBndrun") { | ||
| // Local copies so the doLast closure captures only serializable values (String, Provider), not | ||
| // the enclosing Kotlin build-script object (required by the configuration cache). | ||
| val bndrunFile = inputBndrun | ||
| val bndrunContent = | ||
| """ | ||
| |-tester: biz.aQute.tester.junit-platform | ||
| |-runfw: org.apache.felix.framework | ||
| |-runee: $runee | ||
| | | ||
| |-runrequires: \ | ||
| | bnd.identity;id='$bsn',\ | ||
| | bnd.identity;id='junit-jupiter-engine',\ | ||
| | bnd.identity;id='junit-platform-launcher' | ||
| """.trimMargin() | ||
| inputs.property("content", bndrunContent) | ||
| outputs.file(bndrunFile) | ||
| doLast { | ||
| bndrunFile.get().asFile.apply { parentFile.mkdirs() }.writeText(bndrunContent) | ||
| } | ||
| } | ||
|
|
||
| val resolvedBndrun = layout.buildDirectory.file("test.bndrun") | ||
| val resolve = tasks.register<Resolve>("resolve") { | ||
| dependsOn(testingBundle, generateBndrun) | ||
| description = "Resolve the semconv OSGi test suite" | ||
| group = JavaBasePlugin.VERIFICATION_GROUP | ||
| bndrun = inputBndrun.get().asFile | ||
| outputBndrun = resolvedBndrun | ||
| bundles = files(testRuntimeClasspath, testingBundle.get().archiveFile) | ||
| // The resolved bndrun embeds an absolute path to the input, so it is not safe to share via cache. | ||
| outputs.cacheIf { false } | ||
| } | ||
|
|
||
| tasks.register<TestOSGi>("testOsgi") { | ||
| dependsOn(resolve) | ||
| description = "Run the semconv OSGi test suite inside an Apache Felix container" | ||
| group = JavaBasePlugin.VERIFICATION_GROUP | ||
| bndrun = resolvedBndrun | ||
| bundles = files(testRuntimeClasspath, testingBundle.get().archiveFile) | ||
| // BND reports success when zero tests ran (e.g. if bundles failed to start). Fail explicitly. | ||
| val testResultsDir = layout.buildDirectory.dir("test-results/$name") | ||
| doLast { | ||
| check(testResultsDir.get().asFile.listFiles()?.isNotEmpty() == true) { | ||
| "No OSGi test results found — bundles may have failed to start. Check the output above." | ||
| } | ||
| } | ||
| } | ||
|
|
||
| tasks { | ||
| named<Jar>("jar") { | ||
| enabled = false | ||
| } | ||
| named<Test>("test") { | ||
| // Replace plain JUnit execution with the in-container OSGi test. | ||
| actions.clear() | ||
| dependsOn("testOsgi") | ||
| } | ||
| } |
39 changes: 39 additions & 0 deletions
39
osgi-test/src/test/java/io/opentelemetry/semconv/integrationtest/osgi/SemconvOsgiTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.semconv.integrationtest.osgi; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
|
|
||
| import io.opentelemetry.api.common.AttributeKey; | ||
| import io.opentelemetry.semconv.SchemaUrls; | ||
| import io.opentelemetry.semconv.ServiceAttributes; | ||
| import io.opentelemetry.semconv.incubating.ServiceIncubatingAttributes; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.junit.jupiter.api.extension.ExtendWith; | ||
| import org.osgi.test.junit5.context.BundleContextExtension; | ||
|
|
||
| /** | ||
| * Boots the semconv and semconv-incubating bundles inside a real OSGi (Apache Felix) container and | ||
| * exercises their exported packages. If either bundle's generated OSGi metadata is wrong (missing | ||
| * exports, unsatisfiable imports), the bundle fails to resolve and these tests never run — which | ||
| * the build treats as a failure. | ||
| */ | ||
| @ExtendWith(BundleContextExtension.class) | ||
| public class SemconvOsgiTest { | ||
|
|
||
| @Test | ||
| public void stableAttributesAreUsable() { | ||
| AttributeKey<String> serviceName = ServiceAttributes.SERVICE_NAME; | ||
| assertThat(serviceName.getKey()).isEqualTo("service.name"); | ||
| assertThat(SchemaUrls.V1_41_1).isEqualTo("https://opentelemetry.io/schemas/1.41.1"); | ||
| } | ||
|
|
||
| @Test | ||
| public void incubatingAttributesAreUsable() { | ||
| AttributeKey<String> instanceId = ServiceIncubatingAttributes.SERVICE_INSTANCE_ID; | ||
| assertThat(instanceId.getKey()).isEqualTo("service.instance.id"); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.