Dependency Automation Roadmap
This document outlines the path to full automation for Android dependency management in the Datadog MAUI SDK bindings.
Current State vs. Desired State
Current Implementation (Basic)
Script: scripts/generate-android-dependencies.sh
What it does:
- ✅ Fetches POM file from Maven Central
- ✅ Parses
<dependencies>section - ✅ Filters out test-scope dependencies
- ✅ Sets
Bind="false"for non-Datadog artifacts - ✅ Outputs
AndroidMavenLibraryXML snippets
What it does NOT do:
- ❌ Check if NuGet packages exist for dependencies
- ❌ Query package versions from NuGet.org
- ❌ Handle transitive dependencies from MAUI
- ❌ Generate
AndroidIgnoredJavaDependencyentries - ❌ Generate
PackageReferenceentries - ❌ Make intelligent placement decisions (core vs. feature module)
- ❌ Validate against known dependency patterns
Future Configuration-Driven System
Configuration-Driven Approach:
# Dependencies categorized by action
download:
- groupId: com.lyft.kronos
artifactId: kronos-android
nuget:
- groupId: com.google.code.gson
artifactId: gson
nugetPackage: GoogleGson
skip:
- groupId: androidx.core
artifactId: core
reason: Transitive from Material/Navigation packages
Advantages:
- ✅ Human-readable configuration
- ✅ Explicit categorization of each dependency
- ✅ Documents the “why” (reason field)
- ✅ Easy to version control and review changes
- ✅ Can be used by scripts to generate project files
Recommended Enhanced System
Architecture
┌─────────────────────────────────────────────────────────────┐
│ │
│ 1. POM Fetcher (Maven Central API) │
│ - Fetches POM for each Datadog module │
│ - Extracts compile/runtime dependencies │
│ │
└─────────────────┬───────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ │
│ 2. Dependency Categorizer │
│ - Checks deps-config.yaml for known mappings │
│ - Queries NuGet.org API for Xamarin packages │
│ - Identifies MAUI transitive dependencies │
│ - Determines: nuget / skip / download / internal │
│ │
└─────────────────┬───────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ │
│ 3. Dependency Deduplicator │
│ - Analyzes all modules to find shared dependencies │
│ - Identifies dependencies used by 2+ feature modules │
│ - Marks for centralization in core │
│ │
└─────────────────┬───────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ │
│ 4. Project File Generator │
│ - Core: PackageReference for shared NuGet deps │
│ - Core: AndroidMavenLibrary for shared downloads │
│ - Features: AndroidIgnoredJavaDependency for shared │
│ - Features: Module-specific deps where needed │
│ - All: AndroidIgnoredJavaDependency for MAUI-provided │
│ │
└─────────────────────────────────────────────────────────────┘
Configuration File: deps-config.yaml
Enhanced configuration file format with comprehensive metadata:
# Shared dependencies centralized in core
shared_nuget:
- maven:
groupId: com.google.code.gson
artifactId: gson
version: 2.10.1
nuget:
packageId: GoogleGson
version: 2.11.0
notes: "Complex binding requirements - must use NuGet package"
placement: core
- maven:
groupId: org.jetbrains
artifactId: annotations
version: 13.0
nuget:
packageId: Xamarin.Jetbrains.Annotations
version: 26.0.1.1
minVersion: 26.0.1.1
notes: "Required version >= 26.0.1.1 due to Kotlin stdlib transitive deps"
placement: core
- maven:
groupId: com.squareup.okhttp3
artifactId: okhttp
version: 4.12.0
nuget:
packageId: Square.OkHttp3
version: 4.12.0
placement: core
# Dependencies covered by MAUI (skip in all projects)
maui_transitive:
- maven:
groupId: androidx.core
artifactId: core
reason: "Transitive from Material/Navigation packages in MAUI"
mauiPackage: "Microsoft.Maui.Controls includes androidx.core transitively"
- maven:
groupId: androidx.fragment
artifactId: fragment
reason: "Transitive from Material/Navigation packages"
- maven:
groupId: androidx.recyclerview
artifactId: recyclerview
reason: "Transitive from Material package"
- maven:
groupId: androidx.appcompat
artifactId: appcompat
reason: "Transitive from Material package"
- maven:
groupId: androidx.navigation
artifactId: navigation-runtime
reason: "Direct in MAUI Core (Xamarin.AndroidX.Navigation.Runtime)"
- maven:
groupId: androidx.navigation
artifactId: navigation-fragment
reason: "Direct in MAUI Core (Xamarin.AndroidX.Navigation.Fragment)"
- maven:
groupId: com.google.android.material
artifactId: material
reason: "Direct in MAUI Core (Xamarin.Google.Android.Material)"
- maven:
groupId: org.jetbrains.kotlin
artifactId: kotlin-stdlib
reason: "Embedded in SDK, also available as Xamarin.Kotlin.StdLib"
- maven:
groupId: org.jetbrains.kotlin
artifactId: kotlin-reflect
reason: "Embedded in SDK, also available as Xamarin.Kotlin.Reflect"
# Dependencies without NuGet bindings (download AAR/JAR)
download:
- maven:
groupId: com.lyft.kronos
artifactId: kronos-android
reason: "No NuGet binding available"
placement: core
- maven:
groupId: com.lyft.kronos
artifactId: kronos-java
reason: "No NuGet binding available"
placement: core
- maven:
groupId: org.jctools
artifactId: jctools-core
reason: "No NuGet binding available"
placement: trace # Used only by trace module
- maven:
groupId: com.google.re2j
artifactId: re2j
reason: "No NuGet binding available"
placement: trace # Used only by trace module
- maven:
groupId: io.opentracing
artifactId: opentracing-api
reason: "No NuGet binding available"
notes: "Only needed for trace-otel integration"
- maven:
groupId: androidx.compose.runtime
artifactId: runtime
reason: "Compose support - check if MAUI includes it"
placement: session-replay
- maven:
groupId: androidx.metrics
artifactId: metrics-performance
reason: "Not available on Maven Central (Google Maven only)"
action: ignore # Can't download, not critical
# Module-specific NuGet dependencies (not shared)
module_specific_nuget:
- maven:
groupId: androidx.work
artifactId: work-runtime
nuget:
packageId: Xamarin.AndroidX.Work.Runtime
version: 2.10.0
usedBy: [core, rum, logs, trace, session-replay, ndk, webview, flags]
notes: "Actually used by all modules - should be in shared?"
- maven:
groupId: androidx.recyclerview
artifactId: recyclerview
nuget:
packageId: Xamarin.AndroidX.RecyclerView
version: 1.3.2.7
usedBy: [rum]
notes: "Only RUM needs RecyclerView directly"
# Internal Datadog cross-references
internal:
- maven:
groupId: com.datadoghq
artifactId: dd-sdk-android-core
action: project_reference
notes: "All feature modules reference core"
- maven:
groupId: com.datadoghq
artifactId: dd-sdk-android-internal
action: project_reference
notes: "Core references internal"
# Test dependencies (always ignore)
test:
- groupId: org.junit.platform
- groupId: org.junit.jupiter
- groupId: org.junit.vintage
- groupId: org.mockito
- groupId: org.mockito.kotlin
- groupId: org.assertj
- groupId: com.github.xgouchet.Elmyr
Implementation Plan
Phase 1: Enhanced Configuration (Week 1)
- Create comprehensive deps-config.yaml
- Add placement information
- Add NuGet version mappings
- Add usage patterns (shared vs. module-specific)
- Create validation script
./scripts/validate-deps-config.sh- Validates YAML syntax
- Checks for duplicate entries
- Warns about missing required fields
Phase 2: Dependency Analyzer (Week 2)
- Create analyzer script
./scripts/analyze-dependencies.sh <version>- Fetches all POM files for Datadog modules
- Extracts all dependencies with versions
- Cross-references with deps-config.yaml
- Identifies:
- ✅ Known dependencies (in config)
- ⚠️ Unknown dependencies (need categorization)
- ❌ Conflicting versions
- Output format:
Analyzing Datadog Android SDK v3.5.0 ✅ Known Dependencies (45) ⚠️ Unknown Dependencies (3): - androidx.new.library:new-component:1.0.0 Action: Needs categorization Suggestion: Check NuGet.org for Xamarin.AndroidX.New.Library ❌ Version Conflicts (1): - androidx.lifecycle:lifecycle-runtime Core: 2.8.5 | RUM: 2.8.7 Resolution: Update core to 2.8.7
Phase 3: Project File Generator (Week 3)
- Create generator script
./scripts/generate-binding-projects.sh <version>- Reads deps-config.yaml
- Reads POM files for all modules
- Generates complete .csproj files:
- Core with shared dependencies
- Feature modules with appropriate references
- Correct placement of all dependency types
- Dry-run mode:
./scripts/generate-binding-projects.sh --dry-run 3.5.0- Shows what would be generated
- Allows review before applying
- Diff mode:
./scripts/generate-binding-projects.sh --diff 3.5.0- Shows changes from current .csproj files
- Useful for updates
Phase 4: NuGet Discovery (Week 4)
- Create NuGet API client
./scripts/find-nuget-package.sh androidx.example:example-lib- Queries NuGet.org API
- Searches for Xamarin.AndroidX., Xamarin., GoogleGson, etc.
- Returns package ID and latest version
- Integrate into analyzer
- Automatically suggest NuGet packages for unknown dependencies
- Check if newer versions available
Phase 5: MAUI Dependency Checker (Week 5)
- Create MAUI analyzer
./scripts/check-maui-dependencies.sh- Analyzes MAUI’s transitive dependencies
- Compares with Datadog SDK dependencies
- Identifies overlaps
- Output:
MAUI Transitive Dependencies: ✅ androidx.core:core (1.13.0) - Already in skip list ⚠️ androidx.compose.ui:ui (1.5.0) - Not in config, used by session-replay Suggestion: Add to maui_transitive or verify if needed
Success Metrics
The automated system should achieve:
- Correctness: 100% of dependencies correctly categorized
- Completeness: Zero build errors related to missing/duplicate dependencies
- Maintainability: SDK version updates take < 1 hour (vs. current manual process)
- Documentation: All decisions captured in deps-config.yaml with rationale
- Validation: Automated checks prevent misconfigurations
Migration Path
From Current State
- Keep existing scripts for backward compatibility
- Run new analyzer against current configuration
- Validate that analyzer matches current .csproj files
- Document discrepancies and resolve them
- Switch to generator for next SDK version update
For Next SDK Update (3.6.0)
- Run analyzer with new version
- Review unknown dependencies
- Update deps-config.yaml with categorizations
- Run generator with –diff to review changes
- Apply changes and test
- Document any new patterns learned
Open Questions
1. How to handle version conflicts?
Options:
- A) Always use highest version (safest)
- B) Allow configuration to pin versions
- C) Warn and require manual resolution
Recommendation: A + C (use highest, but warn about significant version jumps)
2. When to check for newer NuGet packages?
Options:
- A) Every run (slow, but always current)
- B) Only on SDK version updates
- C) Manual trigger with –check-updates flag
Recommendation: C (manual trigger to avoid slow runs)
3. How to handle breaking changes in NuGet packages?
Example: Xamarin.AndroidX.* packages change namespaces
Solution: Add to deps-config.yaml:
shared_nuget:
- maven:
groupId: androidx.core
artifactId: core
nuget:
packageId: Xamarin.AndroidX.Core
version: 1.15.0.2
breaking_changes:
- version: 1.14.0
note: "Namespace changed from AndroidX.Core to Xamarin.AndroidX.Core"
4. Should we auto-commit generated files?
Options:
- A) Yes, with descriptive commit message
- B) No, always require manual review
- C) Dry-run by default, –apply flag to commit
Recommendation: C (safe default, easy to apply when ready)
Comparison: Manual vs. Automated
| Task | Manual Time | Automated Time | Savings |
|---|---|---|---|
| Fetch POMs | 10 min | Instant | 10 min |
| Categorize deps | 30 min | Instant | 30 min |
| Check NuGet | 20 min | Instant | 20 min |
| Generate XML | 40 min | Instant | 40 min |
| Validate & test | 30 min | 30 min | 0 min |
| Total | 2h 10min | 30 min | 1h 40min |
ROI: After 3 SDK updates, the automation effort pays for itself.
Next Steps
- ✅ Document current patterns (DONE - this document)
- ⏭️ Create enhanced deps-config.yaml
- ⏭️ Build dependency analyzer
- ⏭️ Build project file generator
- ⏭️ Test on next SDK version update
- ⏭️ Iterate based on learnings
Document Version: 1.0 Last Updated: 2026-01-16 Status: Roadmap (Not Yet Implemented)