The C# clients under src/OsduCsharpClient/Generated/ are produced by running Kiota against the OpenAPI specs in openapi_specs/. This output is not committed to the repository for the following reasons:
- Nobody can accidentally edit it. If the generated code is not in the repository, it cannot be hand-edited. Any change must go through the spec and the generator — the only correct way to change it.
- The spec is the source of truth. Committing generated code creates a second source of truth that can silently drift from the spec.
- Diffs stay meaningful. A spec change generates hundreds of touched lines across dozens of files. Keeping generated code out of git means pull request diffs show only what actually changed.
- Reproducible by design. Given the same spec and the same Kiota version, generation is deterministic. Storing the result is redundant.
Consumers of the published NuGet package can still browse the generated client code through their IDE (Visual Studio, Rider, VS Code with C# Dev Kit) using decompilation and the included XML documentation. AI coding assistants also work against the installed package. Contributors working in this repository should run python3 generate_all.py once after cloning to have the generated code available locally.
Clone the repo, then generate the clients and build:
git clone https://github.com/equinor/osdu-csharp-client.git
cd osdu-csharp-client
python3 generate_all.py
dotnet build OsduCsharpClient.slnxProvide configuration (e.g. appsettings.local.json or Osdu__* environment variables) before running tests — see docs/environment-and-tests.md.
dotnet test OsduCsharpClient.slnxReleases are automated using Release Please.
How it works:
- On merge to
main, Release Please checks new commits since the last release using the Conventional Commits format. - When releasable changes are found, Release Please creates or updates a release pull request that bumps the version in
OsduCsharpClient.csprojand updatesCHANGELOG.md. - When the release pull request is merged, the release workflow creates a GitHub release and publishes the NuGet package.
Specs in openapi_specs/ are updated manually: fetch the spec from a deployed service (e.g. <server>/api/<service>/.../openapi.json) or from the upstream OSDU service repository, and commit it. Update one service at a time so the diff stays reviewable.
Warning: The raw upstream specs are not always generator-friendly. This repository may intentionally apply local edits to files in
openapi_specs/to improve generated client quality. Checkgit diffagainst the previous spec before committing.
To regenerate all C# clients from the specs in openapi_specs/:
python3 generate_all.pyThis iterates through all JSON and YAML specs in openapi_specs/ and runs kiota generate for each service into src/OsduCsharpClient/Generated/<ServiceName>/. It also handles minor spec patches before invoking Kiota:
- missing
info.version - non-standard
< * >wildcard properties - YAML timestamp normalization
- untyping the free-form OSDU
datafield onRecord(Storage, Dataset, Wellbore DDMS) andRecordMergePatchRequest(StoragePATCH /records/{id}) so Kiota emits anUntypedNodeinstead of an empty*_dataclass (#38)
These patches are applied in memory only — the files in openapi_specs/ are not modified.
Warning: Do not hand-edit files under
src/OsduCsharpClient/Generated/. They are generated artifacts and will be overwritten the next timegenerate_all.pyis run. Make changes inopenapi_specs/and/or the generation scripts instead.
-
Add the OpenAPI spec to
openapi_specs/(.json,.yaml, or.yml). -
Regenerate —
generate_all.pyauto-discovers all specs, so no script changes are needed:python3 generate_all.py
This creates
src/OsduCsharpClient/Generated/<PascalCaseName>/with a<PascalCaseName>Clientclass. -
Register the endpoint in
src/OsduCsharpClient/Facade/ServiceRegistry.cs:new("my_service", "/api/my-service/v1"),
The attribute name (snake_case) must match the property name you will add to
OsduClient. -
Expose the typed property in
src/OsduCsharpClient/Facade/OsduClient.cs:- Add a
usingfor the generated namespace (e.g.using Equinor.OsduCsharpClient.MyService;) - Add a backing field:
private MyServiceClient? _myService; - Add a public property:
public MyServiceClient MyService => _myService ??= Build(ref _myService, "my_service");
- Add a
-
Update the README services table in
README.md. -
Update the unit tests — the service count assertions in
tests/OsduCsharpClient.Tests/ServiceRegistryTests.csandtests/OsduCsharpClient.Tests/OsduClientTests.cswill fail until updated.
openapi_specs/ OpenAPI specs (.json / .yaml / .yml)
src/
OsduCsharpClient/
Generated/ Generated C# clients — gitignored, re-run generate_all.py
<ServiceName>/ One subfolder per service (e.g. Search/, Storage/)
Facade/
Auth/ ITokenProvider + MSAL implementations
DataPartitionHandler.cs DelegatingHandler for data-partition-id injection
LoggingHandler.cs DelegatingHandler for HTTP request/response logging
OsduClient.cs High-level facade with typed per-service properties
OsduConfig.cs Configuration record (FromConfiguration binder)
OsduException.cs Typed exception for auth/config/API errors
ServiceRegistry.cs Static service → endpoint mapping
tests/
OsduCsharpClient.IntegrationTests/ xUnit integration tests (require live OSDU server)
OsduCsharpClient.Tests/ xUnit unit tests (no network required)
generate_all.py Regenerates all C# clients via Kiota