Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,31 @@ deploy_to_maven_central:
- 'workspace/dd-trace-api/build/libs/*.jar'
- 'workspace/dd-trace-ot/build/libs/*.jar'

deploy_snapshot_with_ddprof_snapshot:
extends: .gradle_build
stage: publish
needs: [ build ]
variables:
CACHE_TYPE: "lib"
rules:
- if: '$POPULATE_CACHE'
when: never
# Manual trigger only - for testing with ddprof snapshot versions
- when: manual
allow_failure: true
script:
- export MAVEN_CENTRAL_USERNAME=$(aws ssm get-parameter --region us-east-1 --name ci.dd-trace-java.central_username --with-decryption --query "Parameter.Value" --out text)
- export MAVEN_CENTRAL_PASSWORD=$(aws ssm get-parameter --region us-east-1 --name ci.dd-trace-java.central_password --with-decryption --query "Parameter.Value" --out text)
- export GPG_PRIVATE_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-trace-java.signing.gpg_private_key --with-decryption --query "Parameter.Value" --out text)
- export GPG_PASSWORD=$(aws ssm get-parameter --region us-east-1 --name ci.dd-trace-java.signing.gpg_passphrase --with-decryption --query "Parameter.Value" --out text)
- echo "Publishing dd-trace-java snapshot with ddprof snapshot dependency"
- ./gradlew -PbuildInfo.build.number=$CI_JOB_ID -PddprofUseSnapshot publishToSonatype -PskipTests $GRADLE_ARGS
artifacts:
paths:
- 'workspace/dd-java-agent/build/libs/*.jar'
- 'workspace/dd-trace-api/build/libs/*.jar'
- 'workspace/dd-trace-ot/build/libs/*.jar'

deploy_artifacts_to_github:
stage: publish
image: registry.ddbuild.io/images/dd-octo-sts-ci-base:2025.06-1
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ description = "dd-trace-java"
val isCI = providers.environmentVariable("CI")

apply(from = rootDir.resolve("gradle/repositories.gradle"))
apply(from = rootDir.resolve("gradle/ddprof-override.gradle"))

spotless {
// only resolve the spotless dependencies once in the build
Expand Down
7 changes: 7 additions & 0 deletions dd-java-agent/ddprof-lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ dependencies {
api project(':dd-trace-api')
}

// Log information about ddprof version being used
afterEvaluate {
if (rootProject.hasProperty('ddprofUseSnapshot')) {
logger.lifecycle("${project.name}: Using ddprof SNAPSHOT version ${rootProject.ext.ddprofSnapshotVersion}")
}
}

tasks.named("shadowJar", ShadowJar) {
dependencies {
deps.excludeShared
Expand Down
141 changes: 141 additions & 0 deletions docs/publishing-with-ddprof-snapshot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Publishing dd-trace-java Snapshots with ddprof SNAPSHOT Dependency

## Overview

This feature allows publishing dd-trace-java snapshot versions that depend on a ddprof SNAPSHOT version with an incremented minor version.

**ddprof Version Calculation:** Current ddprof version `X.Y.Z` → Dependency becomes `X.(Y+1).0-SNAPSHOT`

**Example:** ddprof `1.34.4` → Uses dependency `1.35.0-SNAPSHOT`

### Version Qualification

To avoid overwriting standard snapshot artifacts, builds with `-PddprofUseSnapshot` will have a `-ddprof` qualifier added to their version:

- Standard snapshot: `1.58.0-SNAPSHOT`
- With ddprof snapshot: `1.58.0-ddprof-SNAPSHOT`

This ensures that both versions can coexist in Maven Central Snapshots repository without conflicts.

## Local Usage

### Testing Dependency Resolution

To verify that the ddprof snapshot version is correctly calculated and applied:

```bash
./gradlew -PddprofUseSnapshot :dd-java-agent:ddprof-lib:dependencies --configuration runtimeClasspath
```

Look for the output:
- `Using ddprof snapshot version: X.Y.0-SNAPSHOT`
- `Modified version for dd-trace-java: 1.58.0-SNAPSHOT -> 1.58.0-ddprof-SNAPSHOT`
- `ddprof-lib: Using ddprof SNAPSHOT version X.Y.0-SNAPSHOT`
- Dependency resolution showing: `com.datadoghq:ddprof:X.Y.Z -> X.(Y+1).0-SNAPSHOT`

### Building with ddprof Snapshot

To build the project with the ddprof snapshot dependency:

```bash
./gradlew build -PddprofUseSnapshot
```

### Publishing to Maven Central Snapshots

To publish artifacts with the ddprof snapshot dependency:

```bash
./gradlew publishToSonatype -PddprofUseSnapshot -PskipTests
```

**Note:** You must have the required credentials configured:
- `MAVEN_CENTRAL_USERNAME`
- `MAVEN_CENTRAL_PASSWORD`
- `GPG_PRIVATE_KEY`
- `GPG_PASSWORD`

## GitLab CI Usage

### Manual Job Trigger

A GitLab CI job named `deploy_snapshot_with_ddprof_snapshot` is available for manual execution.

**To trigger:**
1. Navigate to the pipeline in GitLab CI
2. Find the `deploy_snapshot_with_ddprof_snapshot` job in the `publish` stage
3. Click the manual play button to trigger it

**What it does:**
- Builds dd-trace-java with `-PddprofUseSnapshot`
- Publishes to Maven Central Snapshots repository
- Produces artifacts with the ddprof snapshot dependency

**When to use:**
- Testing integration with unreleased ddprof features
- Validating compatibility before ddprof release
- Creating test builds for early adopters

## Implementation Details

### Files Modified

1. **`gradle/ddprof-override.gradle`** - Core logic for version calculation and dependency override
2. **`build.gradle.kts`** - Applies the ddprof-snapshot configuration
3. **`dd-java-agent/ddprof-lib/build.gradle`** - Logging for snapshot version usage
4. **`.gitlab-ci.yml`** - New CI job for snapshot publishing

### How It Works

1. The Gradle property `-PddprofUseSnapshot` activates the feature
2. The configuration reads `gradle/libs.versions.toml` to get the current ddprof version
3. Version is parsed using regex: `ddprof = "X.Y.Z"`
4. Snapshot version is calculated: `X.(Y+1).0-SNAPSHOT`
5. **The dd-trace-java version is modified** to add a `-ddprof` qualifier:
- `1.58.0-SNAPSHOT` → `1.58.0-ddprof-SNAPSHOT`
- This prevents overwriting standard snapshot artifacts
6. Gradle's `resolutionStrategy.eachDependency` overrides all ddprof dependencies to use the snapshot version
7. The build and publish proceed with the modified version and overridden dependency

### Dependency Resolution Override

The override is applied globally to all configurations in all projects:

```groovy
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'com.datadoghq' && details.requested.name == 'ddprof') {
details.useVersion(ddprofSnapshotVersion)
details.because("Using ddprof snapshot version for integration testing")
}
}
}
```

This ensures that even transitive dependencies on ddprof are overridden.

## Limitations

- Only works with semantic versioning in format `X.Y.Z`
- Requires ddprof SNAPSHOT to be published to Maven Central Snapshots repository
- Cannot override local JAR files specified with `-Pddprof.jar=/path/to/jar`

## Troubleshooting

### "Could not find com.datadoghq:ddprof:X.Y.0-SNAPSHOT"

**Cause:** The calculated ddprof snapshot version doesn't exist in Maven Central Snapshots.

**Solutions:**
- Verify ddprof has published the snapshot version
- Check Maven Central Snapshots repository: https://central.sonatype.com/repository/maven-snapshots/
- Wait for ddprof CI to complete if a new snapshot is being published

### Version not being overridden

**Cause:** The property might not be correctly set or parsed.

**Solutions:**
- Ensure you're using `-PddprofUseSnapshot` (not `-DddprofUseSnapshot`)
- Check Gradle output for "Using ddprof snapshot version" message
- Run with `--info` flag to see detailed dependency resolution logs
73 changes: 73 additions & 0 deletions gradle/ddprof-override.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Configuration for using ddprof snapshot versions
// When -PddprofUseSnapshot=true is set, this will:
// 1. Parse the current ddprof version from libs.versions.toml
// 2. Calculate the next minor snapshot version: X.Y.Z -> X.(Y+1).0-SNAPSHOT
// 3. Override the ddprof dependency resolution to use the snapshot version
// 4. Add a qualifier to the dd-trace-java version to avoid overwriting standard snapshots

def ddprofUseSnapshot = project.hasProperty("ddprofUseSnapshot")

if (ddprofUseSnapshot) {
def ddprofSnapshotVersion = calculateDdprofSnapshotVersion()
logger.lifecycle("Using ddprof snapshot version: ${ddprofSnapshotVersion}")

// Store the calculated version as an extra property for use in subprojects
rootProject.ext.ddprofSnapshotVersion = ddprofSnapshotVersion

// Add qualifier to the project version to differentiate from standard snapshots
// This ensures we don't overwrite the regular SNAPSHOT artifacts
allprojects {
def originalVersion = version.toString()
if (originalVersion.contains('-SNAPSHOT')) {
// Insert qualifier before -SNAPSHOT: X.Y.Z-SNAPSHOT -> X.Y.Z-ddprof-SNAPSHOT
version = originalVersion.replace('-SNAPSHOT', '-ddprof-SNAPSHOT')
} else if (originalVersion.contains('-')) {
// For versions with trailer: X.Y.Z-12-g8ab3f42d -> X.Y.Z-ddprof-12-g8ab3f42d
def parts = originalVersion.split('-', 2)
version = "${parts[0]}-ddprof-${parts[1]}"
} else {
// For release versions (shouldn't happen, but handle it): X.Y.Z -> X.Y.Z-ddprof
version = "${originalVersion}-ddprof"
}
logger.lifecycle("Modified version for ${project.name}: ${originalVersion} -> ${version}")
}

// Override the ddprof dependency resolution for all configurations
allprojects {
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'com.datadoghq' && details.requested.name == 'ddprof') {
details.useVersion(ddprofSnapshotVersion)
details.because("Using ddprof snapshot version for integration testing")
}
}
}
}
}

def calculateDdprofSnapshotVersion() {
// Read the libs.versions.toml file
def versionsFile = rootProject.file('gradle/libs.versions.toml')
if (!versionsFile.exists()) {
throw new GradleException("Could not find gradle/libs.versions.toml")
}

def currentVersion = null
versionsFile.eachLine { line ->
// Look for the ddprof version line: ddprof = "X.Y.Z"
def matcher = line =~ /^\s*ddprof\s*=\s*"([0-9]+)\.([0-9]+)\.([0-9]+)"\s*$/
if (matcher) {
def major = matcher[0][1]
def minor = matcher[0][2]
// Increment the minor version
def nextMinor = (minor as Integer) + 1
currentVersion = "${major}.${nextMinor}.0-SNAPSHOT"
}
}

if (currentVersion == null) {
throw new GradleException("Could not parse ddprof version from gradle/libs.versions.toml")
}

return currentVersion
}
Loading