Concepts
A cloud provider running the Open Subsurface Data Universe (OSDU) has to keep two things at once: compatibility with the community code, and its own Service Provider Interface (SPI) implementation. OSDU keeps community standards and cloud-specific code in separate layers. The diagram below shows how Microsoft keeps that separation through a fork:
graph TB
subgraph Community["OSDU Community Repository - Upstream"]
Shared["API, Core Code and SPI Interfaces"]
Seed["Azure Provider and Test Source<br/>Last upstream revision containing them"]
end
Shared -->|Filtered sync| Generated["fork_upstream<br/>Shared code and Azure module references<br/>No Azure source"]
subgraph Fork["Azure Service Fork - fork_integration and main"]
Core["API and Core Code"] --- Interface["SPI Interfaces"] --- Azure["Fork-owned Azure Provider and Tests"]
end
Generated -->|Cascade shared changes| Core
Seed -.->|Seed once at initialization| Azure
style Community fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
style Fork fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style Generated fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
style Interface fill:#fff3e0,stroke:#e65100,stroke-width:2px
style Azure fill:#e3f2fd,stroke:#1565c0,stroke-width:2px The SPI Interface (orange) is the code boundary: shared service logic calls an interface implemented by the Azure provider. Source ownership follows a separate boundary. Sync regenerates fork_upstream from shared upstream code and injects references to the Azure modules, but excludes the provider implementations themselves.
Upstream plans to remove its Azure implementations. Initialization therefore seeds provider/<svc>-azure and testing/<svc>-test-azure once, from the newest upstream revision that still contains them. Those trees are then maintained in the service fork on fork_integration and main. Cascade combines shared changes with that fork-owned source and updates its Maven version wiring. Late upstream fixes to Azure source need an explicit port. See ADR-038: Upstream Filter Transform and One-Time Azure Seeding.
Upstream-Owned Components include OSDU core interfaces, community-validated business logic, standard data models, and shared tests.
Fork-Owned Components include the Azure provider and Azure test source, plus the fork's engineering configuration and build machinery.
The Fork Management Problem
A long-lived fork of an upstream OSDU repository runs into four recurring problems:
Integration Complexity
Manual synchronization is slow, and slowest when an upstream change touches an interface the Azure SPI implementation depends on.
Divergence Risk
Local modifications drift from upstream over time, and each sync gets harder than the last.
Blocking Dependencies
In a shared tree, a build or test failure in any provider's SPI implementation can block merging changes for every other provider.
Release Coordination
Without tracking, nobody can say which upstream release a fork version contains.
| Aspect | Manual Fork Management | This System |
|---|---|---|
| Synchronization | Weekly or monthly, by hand | Daily, as a reviewable PR |
| Conflict Resolution | Wherever the merge happened | Isolated in fork_integration |
| Release Coordination | Tracked by hand, if at all | Correlation tags against upstream releases |
| Integration Testing | After conflicts are resolved | At each branch stage |
The Automation Solution
The system isolates each stage of integration in its own branch. Changes flow through fork_upstream, then fork_integration, then main, with validation at each step, so a failure stops at the stage where it happened.
graph TD
A[OSDU Community Repository - Upstream]
A -->|Filtered sync| B
subgraph Azure["Azure SPI Repository"]
B[fork_upstream<br/>Shared code; no Azure source]
B --> C[fork_integration<br/>Shared code + fork-owned Azure source]
C --> D[main<br/>Shared code + fork-owned Azure source]
end
style A fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
style Azure fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style B fill:#fff3e0,stroke:#e65100,stroke-width:2px
style C fill:#fce4ec,stroke:#c2185b,stroke-width:2px
style D fill:#e3f2fd,stroke:#1565c0,stroke-width:2px What the workflows do:
Upstream Synchronization
- Daily pull of the upstream tip
- Generated from shared upstream code, with Azure module references but no Azure source
- One PR per upstream state, with the commit list in the body
Conflict Management
- Resolution happens in
fork_integration - A tracking issue records the conflict and the steps to resolve it
- Build and tests run before the change is offered to
main
Release Coordination
- Correlation tags against upstream versions
- Semantic versions computed from conventional commits
- Changelog generated by Release Please
The model extends one tier further. A customer organization can run a true GitHub fork of a service repository through this same machinery in mirror mode: their fork_upstream mirrors the service repository's main verbatim, they build and release with their own credentials, and proven features return as contribution PRs through the fork network. See Fork Tiers.
Why This Matters
The fork team spends its time on the Azure implementation instead of on merges. Upstream changes arrive as reviewable PRs on a predictable cadence, releases record which upstream version they contain, and downstream systems such as Azure Data Manager for Energy get stable release points to consume.