diff --git a/.codegen/_openapi_sha b/.codegen/_openapi_sha index 2ba7e3472..d8ba11803 100644 --- a/.codegen/_openapi_sha +++ b/.codegen/_openapi_sha @@ -1 +1 @@ -46ce086e9005f51eb2c014b1eff2c607cc689c73 \ No newline at end of file +e62e36c7dd18a5b4988253c58fb0b245f7764939 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index ae58747f0..f398a99c4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2232,6 +2232,7 @@ databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/KafkaConfig.java databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/KafkaSource.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/KafkaStreamConfig.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/KafkaSubscriptionMode.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/KinesisStreamConfig.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/LastDistinctFunction.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/LastFunction.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/LastNFunction.java linguist-generated=true @@ -2361,7 +2362,9 @@ databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/Status.java ling databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StddevPopFunction.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StddevSampFunction.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/Stream.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamArnList.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamConnectionConfig.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamNameList.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamSchemaConfig.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamSource.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamSourceConfig.java linguist-generated=true @@ -2604,6 +2607,7 @@ databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/Truncatio databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfoCause.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfoState.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateMode.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateStateInfo.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateStateInfoState.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/ZendeskSupportOptions.java linguist-generated=true diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index d30ee1665..a9989edfd 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -44,6 +44,13 @@ jobs: # to main, preserving the pre-existing hardcoded-main behaviour and # blocking branch releases even via a manual non-main dispatch. RELEASE_REF: ${{ github.repository == 'databricks/terraform-provider-databricks' && github.ref_name || 'main' }} + # Changelog source. databricks/cli builds the release changelog from + # per-PR ``.nextchanges/
/*.md`` fragments and a + # ``.nextchanges/version`` file rather than a single hand-maintained + # ``NEXT_CHANGELOG.md`` (see tagging.py's nextchanges mode). Setting this + # to the fragment directory name opts that repo in; every other synced + # repo leaves it empty and keeps the ``NEXT_CHANGELOG.md`` flow unchanged. + NEXTCHANGES_DIR: ${{ github.repository == 'databricks/cli' && '.nextchanges' || '' }} environment: "release-is" runs-on: group: databricks-protected-runner-group @@ -95,6 +102,10 @@ jobs: # checked out above (``RELEASE_REF``): the dispatched branch for # terraform, main everywhere else. DECO_TAGGING_REF: ${{ env.RELEASE_REF }} + # Non-empty only for databricks/cli (see job-level env). When set, + # tagging.py renders the changelog from ``$NEXTCHANGES_DIR/`` fragments + # instead of ``NEXT_CHANGELOG.md``. + NEXTCHANGES_DIR: ${{ env.NEXTCHANGES_DIR }} run: | if [ -n "$PACKAGES" ]; then uv run --locked tagging.py --package "$PACKAGES" diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 7d2fb79c9..1a9cf6846 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -15,3 +15,10 @@ ### Internal Changes ### API Changes +* Add `kinesisStreamConfig` field for `com.databricks.sdk.service.ml.StreamSourceConfig`. +* Add `mode` field for `com.databricks.sdk.service.pipelines.UpdateInfo`. +* [Breaking] Change `state` field for `com.databricks.sdk.service.bundledeployments.Operation` to type `String` class. +* [Breaking] Change `state` field for `com.databricks.sdk.service.bundledeployments.Resource` to type `String` class. +* [Breaking] Remove `awsAccessKeyId` and `awsSecretAccessKey` fields for `com.databricks.sdk.service.catalog.ModelProviderServiceConfigAmazonBedrockProviderDirectConfig`. +* [Breaking] Remove `clientId`, `clientSecret` and `tenantId` fields for `com.databricks.sdk.service.catalog.ModelProviderServiceConfigAzureOpenAiProviderDirectConfig`. +* [Breaking] Remove `clientId`, `clientSecret` and `tenantId` fields for `com.databricks.sdk.service.catalog.ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig`. \ No newline at end of file diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/bundledeployments/Operation.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/bundledeployments/Operation.java index 1c57f974b..1d7597809 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/bundledeployments/Operation.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/bundledeployments/Operation.java @@ -5,7 +5,6 @@ import com.databricks.sdk.support.Generated; import com.databricks.sdk.support.ToStringer; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; import com.google.protobuf.Timestamp; import java.util.Objects; @@ -86,9 +85,20 @@ public class Operation { * Serialized local config state after the operation. Should be unset for delete operations. * Mutable: may be updated after creation via UpdateOperation. When updating, the caller must echo * the last-observed `sequence_id` as a concurrency precondition. + * + *

Opaque to this service: the string is stored and returned unchanged. This is deliberately + * not google.protobuf.Value, whose only numeric case is `double number_value`, so parsing the + * client's JSON into it rewrites every integer as a double - `1` reads back as `1.0`, which no + * longer deserializes into an integer field - and silently loses precision above 2^53, which is + * within range for IDs the client records. + * + *

A string rather than bytes: the payload is always UTF-8 JSON, and proto3 JSON maps bytes to + * base64, which inflates every request and response by a third and makes state unreadable in logs + * and API responses. Both generate the same OpenAPI schema ("type": "string"), so the SDKs are + * identical either way. */ @JsonProperty("state") - private JsonNode state; + private String state; /** * Whether the operation succeeded or failed. Mutable: may be updated after creation via @@ -186,12 +196,12 @@ public Long getSequenceId() { return sequenceId; } - public Operation setState(JsonNode state) { + public Operation setState(String state) { this.state = state; return this; } - public JsonNode getState() { + public String getState() { return state; } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/bundledeployments/Resource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/bundledeployments/Resource.java index 08a7607b4..ece1e8489 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/bundledeployments/Resource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/bundledeployments/Resource.java @@ -5,7 +5,6 @@ import com.databricks.sdk.support.Generated; import com.databricks.sdk.support.ToStringer; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; import com.google.protobuf.Timestamp; import java.util.Objects; @@ -46,9 +45,12 @@ public class Resource { @JsonProperty("resource_type") private DeploymentResourceType resourceType; - /** Serialized local config state (what the CLI deployed). */ + /** + * Serialized local config state (what the CLI deployed). Opaque to this service; see + * Operation.state for why this is a string and not google.protobuf.Value. + */ @JsonProperty("state") - private JsonNode state; + private String state; /** * When the last operation that updated this resource's recorded state was applied. Pairs with @@ -120,12 +122,12 @@ public DeploymentResourceType getResourceType() { return resourceType; } - public Resource setState(JsonNode state) { + public Resource setState(String state) { this.state = state; return this; } - public JsonNode getState() { + public String getState() { return state; } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListMcpServicesRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListMcpServicesRequest.java index c56e20e2c..9cac38918 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListMcpServicesRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListMcpServicesRequest.java @@ -16,7 +16,7 @@ public class ListMcpServicesRequest { private Boolean includeBrowse; /** - * Maximum number of MCP services to return. Defaults to 100 when unset or 0; the maximum is 1000. + * Maximum number of MCP services to return. Defaults to 100 when unset or 0; the maximum is 100. * Use `next_page_token` to retrieve additional pages. */ @JsonIgnore diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListModelProviderServicesRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListModelProviderServicesRequest.java index e8b984e0c..f490cab76 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListModelProviderServicesRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListModelProviderServicesRequest.java @@ -20,7 +20,7 @@ public class ListModelProviderServicesRequest { /** * Maximum number of provider services to return. Defaults to 100 when unset or 0; the maximum is - * 1000. Use `next_page_token` to retrieve additional pages. + * 100. Use `next_page_token` to retrieve additional pages. */ @JsonIgnore @QueryParam("page_size") diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListModelServicesRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListModelServicesRequest.java index b86273a79..27bdff0f3 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListModelServicesRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ListModelServicesRequest.java @@ -19,7 +19,7 @@ public class ListModelServicesRequest { /** * Maximum number of model services to return. Defaults to 100 when unset or 0; the maximum is - * 1000. Use `next_page_token` to retrieve additional pages. + * 100. Use `next_page_token` to retrieve additional pages. */ @JsonIgnore @QueryParam("page_size") diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigAmazonBedrockProviderDirectConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigAmazonBedrockProviderDirectConfig.java index b20dc7a51..88ec0e3b1 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigAmazonBedrockProviderDirectConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigAmazonBedrockProviderDirectConfig.java @@ -25,22 +25,6 @@ public class ModelProviderServiceConfigAmazonBedrockProviderDirectConfig { @JsonProperty("aws_access_key") private ModelProviderServiceConfigAwsAccessKey awsAccessKey; - /** - * Deprecated flat AWS access key ID. Superseded by `aws_access_key.access_key_id`. Kept for one - * migration cycle; the handler mirrors it to/from `aws_access_key`. Treated as - * username-equivalent (not a secret value): round-trips on reads and is scrubbed from audit logs. - */ - @JsonProperty("aws_access_key_id") - private String awsAccessKeyId; - - /** - * Deprecated flat AWS secret access key. Superseded by `aws_access_key.secret_access_key`. Kept - * for one migration cycle; the handler mirrors it to/from `aws_access_key`. Supplied as inline - * plaintext via `ProviderSecret.plaintext`. - */ - @JsonProperty("aws_secret_access_key") - private ModelProviderServiceConfigProviderSecret awsSecretAccessKey; - /** AWS region where the Bedrock endpoint is hosted (e.g., `us-east-1`). Required on Create. */ @JsonProperty("region") private String region; @@ -66,26 +50,6 @@ public ModelProviderServiceConfigAwsAccessKey getAwsAccessKey() { return awsAccessKey; } - public ModelProviderServiceConfigAmazonBedrockProviderDirectConfig setAwsAccessKeyId( - String awsAccessKeyId) { - this.awsAccessKeyId = awsAccessKeyId; - return this; - } - - public String getAwsAccessKeyId() { - return awsAccessKeyId; - } - - public ModelProviderServiceConfigAmazonBedrockProviderDirectConfig setAwsSecretAccessKey( - ModelProviderServiceConfigProviderSecret awsSecretAccessKey) { - this.awsSecretAccessKey = awsSecretAccessKey; - return this; - } - - public ModelProviderServiceConfigProviderSecret getAwsSecretAccessKey() { - return awsSecretAccessKey; - } - public ModelProviderServiceConfigAmazonBedrockProviderDirectConfig setRegion(String region) { this.region = region; return this; @@ -112,24 +76,19 @@ public boolean equals(Object o) { ModelProviderServiceConfigAmazonBedrockProviderDirectConfig that = (ModelProviderServiceConfigAmazonBedrockProviderDirectConfig) o; return Objects.equals(awsAccessKey, that.awsAccessKey) - && Objects.equals(awsAccessKeyId, that.awsAccessKeyId) - && Objects.equals(awsSecretAccessKey, that.awsSecretAccessKey) && Objects.equals(region, that.region) && Objects.equals(serviceCredential, that.serviceCredential); } @Override public int hashCode() { - return Objects.hash( - awsAccessKey, awsAccessKeyId, awsSecretAccessKey, region, serviceCredential); + return Objects.hash(awsAccessKey, region, serviceCredential); } @Override public String toString() { return new ToStringer(ModelProviderServiceConfigAmazonBedrockProviderDirectConfig.class) .add("awsAccessKey", awsAccessKey) - .add("awsAccessKeyId", awsAccessKeyId) - .add("awsSecretAccessKey", awsSecretAccessKey) .add("region", region) .add("serviceCredential", serviceCredential) .toString(); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigAzureOpenAiProviderDirectConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigAzureOpenAiProviderDirectConfig.java index 71971e7e5..fd5bd7939 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigAzureOpenAiProviderDirectConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigAzureOpenAiProviderDirectConfig.java @@ -33,21 +33,6 @@ public class ModelProviderServiceConfigAzureOpenAiProviderDirectConfig { @JsonProperty("base_url") private String baseUrl; - /** - * Deprecated flat Entra client ID. Superseded by `entra_service_principal.client_id`. Kept for - * one migration cycle; the handler mirrors it to/from `entra_service_principal`. - */ - @JsonProperty("client_id") - private String clientId; - - /** - * Deprecated flat Entra client secret. Superseded by `entra_service_principal.client_secret`. - * Kept for one migration cycle; the handler mirrors it to/from `entra_service_principal`. - * Supplied as inline plaintext via `ProviderSecret.plaintext`. - */ - @JsonProperty("client_secret") - private ModelProviderServiceConfigProviderSecret clientSecret; - /** * Entra ID (service principal) auth. Mutually exclusive with `api_key` and `service_credential`. * Supersedes the flat `tenant_id` / `client_id` / `client_secret` fields. @@ -66,13 +51,6 @@ public class ModelProviderServiceConfigAzureOpenAiProviderDirectConfig { @JsonProperty("service_credential") private ModelProviderServiceConfigServiceCredential serviceCredential; - /** - * Deprecated flat Entra tenant ID. Superseded by `entra_service_principal.tenant_id`. Kept for - * one migration cycle; the handler mirrors it to/from `entra_service_principal`. - */ - @JsonProperty("tenant_id") - private String tenantId; - public ModelProviderServiceConfigAzureOpenAiProviderDirectConfig setApiKey( ModelProviderServiceConfigProviderSecret apiKey) { this.apiKey = apiKey; @@ -92,25 +70,6 @@ public String getBaseUrl() { return baseUrl; } - public ModelProviderServiceConfigAzureOpenAiProviderDirectConfig setClientId(String clientId) { - this.clientId = clientId; - return this; - } - - public String getClientId() { - return clientId; - } - - public ModelProviderServiceConfigAzureOpenAiProviderDirectConfig setClientSecret( - ModelProviderServiceConfigProviderSecret clientSecret) { - this.clientSecret = clientSecret; - return this; - } - - public ModelProviderServiceConfigProviderSecret getClientSecret() { - return clientSecret; - } - public ModelProviderServiceConfigAzureOpenAiProviderDirectConfig setEntraServicePrincipal( ModelProviderServiceConfigEntraServicePrincipal entraServicePrincipal) { this.entraServicePrincipal = entraServicePrincipal; @@ -131,15 +90,6 @@ public ModelProviderServiceConfigServiceCredential getServiceCredential() { return serviceCredential; } - public ModelProviderServiceConfigAzureOpenAiProviderDirectConfig setTenantId(String tenantId) { - this.tenantId = tenantId; - return this; - } - - public String getTenantId() { - return tenantId; - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -148,23 +98,13 @@ public boolean equals(Object o) { (ModelProviderServiceConfigAzureOpenAiProviderDirectConfig) o; return Objects.equals(apiKey, that.apiKey) && Objects.equals(baseUrl, that.baseUrl) - && Objects.equals(clientId, that.clientId) - && Objects.equals(clientSecret, that.clientSecret) && Objects.equals(entraServicePrincipal, that.entraServicePrincipal) - && Objects.equals(serviceCredential, that.serviceCredential) - && Objects.equals(tenantId, that.tenantId); + && Objects.equals(serviceCredential, that.serviceCredential); } @Override public int hashCode() { - return Objects.hash( - apiKey, - baseUrl, - clientId, - clientSecret, - entraServicePrincipal, - serviceCredential, - tenantId); + return Objects.hash(apiKey, baseUrl, entraServicePrincipal, serviceCredential); } @Override @@ -172,11 +112,8 @@ public String toString() { return new ToStringer(ModelProviderServiceConfigAzureOpenAiProviderDirectConfig.class) .add("apiKey", apiKey) .add("baseUrl", baseUrl) - .add("clientId", clientId) - .add("clientSecret", clientSecret) .add("entraServicePrincipal", entraServicePrincipal) .add("serviceCredential", serviceCredential) - .add("tenantId", tenantId) .toString(); } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigGeminiEnterpriseProviderDirectConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigGeminiEnterpriseProviderDirectConfig.java index c8de2af21..a1b12f54f 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigGeminiEnterpriseProviderDirectConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigGeminiEnterpriseProviderDirectConfig.java @@ -7,11 +7,18 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; -/** Direct form of Gemini Enterprise provider config. */ +/** + * Direct form of Gemini Enterprise provider config. + * + *

Authentication is one of two mutually exclusive modes; exactly one must be supplied on Create: + * - API key: set `api_key`, leave `service_credential` unset. - UC service credential: set + * `service_credential`, leave `api_key` unset. + */ @Generated public class ModelProviderServiceConfigGeminiEnterpriseProviderDirectConfig { /** - * Google Gemini Enterprise API key. Required on Create. Supplied as inline plaintext via + * Google Gemini Enterprise API key. Required on Create when using API-key auth; mutually + * exclusive with `service_credential`. Supplied as inline plaintext via * `ProviderSecret.plaintext`. */ @JsonProperty("api_key") diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig.java index dd8d1fdd9..66a533603 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/catalog/ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig.java @@ -33,21 +33,6 @@ public class ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig { @JsonProperty("base_url") private String baseUrl; - /** - * Deprecated flat Entra client ID. Superseded by `entra_service_principal.client_id`. Kept for - * one migration cycle; the handler mirrors it to/from `entra_service_principal`. - */ - @JsonProperty("client_id") - private String clientId; - - /** - * Deprecated flat Entra client secret. Superseded by `entra_service_principal.client_secret`. - * Kept for one migration cycle; the handler mirrors it to/from `entra_service_principal`. - * Supplied as inline plaintext via `ProviderSecret.plaintext`. - */ - @JsonProperty("client_secret") - private ModelProviderServiceConfigProviderSecret clientSecret; - /** * Entra ID (service principal) auth. Mutually exclusive with `api_key` and `service_credential`. * Supersedes the flat `tenant_id` / `client_id` / `client_secret` fields. @@ -67,13 +52,6 @@ public class ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig { @JsonProperty("service_credential") private ModelProviderServiceConfigServiceCredential serviceCredential; - /** - * Deprecated flat Entra tenant ID. Superseded by `entra_service_principal.tenant_id`. Kept for - * one migration cycle; the handler mirrors it to/from `entra_service_principal`. - */ - @JsonProperty("tenant_id") - private String tenantId; - public ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig setApiKey( ModelProviderServiceConfigProviderSecret apiKey) { this.apiKey = apiKey; @@ -93,26 +71,6 @@ public String getBaseUrl() { return baseUrl; } - public ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig setClientId( - String clientId) { - this.clientId = clientId; - return this; - } - - public String getClientId() { - return clientId; - } - - public ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig setClientSecret( - ModelProviderServiceConfigProviderSecret clientSecret) { - this.clientSecret = clientSecret; - return this; - } - - public ModelProviderServiceConfigProviderSecret getClientSecret() { - return clientSecret; - } - public ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig setEntraServicePrincipal( ModelProviderServiceConfigEntraServicePrincipal entraServicePrincipal) { this.entraServicePrincipal = entraServicePrincipal; @@ -133,16 +91,6 @@ public ModelProviderServiceConfigServiceCredential getServiceCredential() { return serviceCredential; } - public ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig setTenantId( - String tenantId) { - this.tenantId = tenantId; - return this; - } - - public String getTenantId() { - return tenantId; - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -151,23 +99,13 @@ public boolean equals(Object o) { (ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig) o; return Objects.equals(apiKey, that.apiKey) && Objects.equals(baseUrl, that.baseUrl) - && Objects.equals(clientId, that.clientId) - && Objects.equals(clientSecret, that.clientSecret) && Objects.equals(entraServicePrincipal, that.entraServicePrincipal) - && Objects.equals(serviceCredential, that.serviceCredential) - && Objects.equals(tenantId, that.tenantId); + && Objects.equals(serviceCredential, that.serviceCredential); } @Override public int hashCode() { - return Objects.hash( - apiKey, - baseUrl, - clientId, - clientSecret, - entraServicePrincipal, - serviceCredential, - tenantId); + return Objects.hash(apiKey, baseUrl, entraServicePrincipal, serviceCredential); } @Override @@ -175,11 +113,8 @@ public String toString() { return new ToStringer(ModelProviderServiceConfigMicrosoftFoundryProviderDirectConfig.class) .add("apiKey", apiKey) .add("baseUrl", baseUrl) - .add("clientId", clientId) - .add("clientSecret", clientSecret) .add("entraServicePrincipal", entraServicePrincipal) .add("serviceCredential", serviceCredential) - .add("tenantId", tenantId) .toString(); } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/AccountIamV2API.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/AccountIamV2API.java index b0ce460b7..d7d40b9bc 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/AccountIamV2API.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/AccountIamV2API.java @@ -27,10 +27,10 @@ public AccountIamV2API(AccountIamV2Service mock) { } /** - * Creates a workspace assignment detail for a principal. Entitlement grants are applied - * individually and non-atomically — if a failure occurs partway through, the principal will be - * assigned to the workspace but with only a subset of the requested entitlements. Use - * GetWorkspaceAssignmentDetail to confirm which entitlements were successfully granted. + * Creates a workspace assignment detail for a principal. Entitlements are granted one at a time + * rather than atomically. If the request fails partway through, the principal stays assigned to + * the workspace with only some of the requested entitlements. Get the assignment detail + * afterwards to confirm which entitlements were granted. */ public WorkspaceAssignmentDetail createWorkspaceAssignmentDetail( CreateWorkspaceAssignmentDetailRequest request) { @@ -45,10 +45,9 @@ public void deleteWorkspaceAssignmentDetail(long workspaceId, long principalId) } /** - * Deletes a workspace assignment detail for a principal, revoking all associated entitlements. - * Entitlement revocations are applied individually and non-atomically — if a failure occurs - * partway through, the principal remains assigned with a subset of its original entitlements, and - * the operation is safe to retry. + * Deletes a workspace assignment detail for a principal, revoking all of its entitlements. + * Entitlements are revoked one at a time rather than atomically. If the request fails partway + * through, the principal stays assigned with some of its original entitlements. Retrying is safe. */ public void deleteWorkspaceAssignmentDetail(DeleteWorkspaceAssignmentDetailRequest request) { impl.deleteWorkspaceAssignmentDetail(request); @@ -92,9 +91,9 @@ public ListWorkspaceAssignmentDetailsResponse listWorkspaceAssignmentDetails(lon } /** - * Lists workspace assignment details for a workspace. For scalability, the response omits the - * per-principal entitlement fields (`entitlements` and `effective_entitlements`); call - * GetWorkspaceAssignmentDetail to read entitlements for a single principal. + * Lists workspace assignment details for a workspace. The response omits the per-principal + * entitlement fields (`entitlements` and `effective_entitlements`). To read the entitlements for + * a single principal, get that principal's assignment detail. */ public ListWorkspaceAssignmentDetailsResponse listWorkspaceAssignmentDetails( ListWorkspaceAssignmentDetailsRequest request) { @@ -111,9 +110,9 @@ public ResolveGroupResponse resolveGroup(ResolveGroupRequest request) { } /** - * Resolves an SP with the given external ID from the customer's IdP. If the SP does not exist, it - * will be created. If the customer is not onboarded onto Automatic Identity Management (AIM), - * this will return an error. + * Resolves a service principal with the given external ID from the customer's IdP. If the service + * principal does not exist, it will be created. If the customer is not onboarded onto Automatic + * Identity Management (AIM), this will return an error. */ public ResolveServicePrincipalResponse resolveServicePrincipal( ResolveServicePrincipalRequest request) { @@ -130,10 +129,9 @@ public ResolveUserResponse resolveUser(ResolveUserRequest request) { } /** - * Updates the entitlements of a directly assigned principal in a workspace. Entitlement changes - * are applied individually and non-atomically — if a failure occurs partway through, only a - * subset of the requested changes may have been applied. Use GetWorkspaceAssignmentDetail to - * confirm the final state. + * Updates the entitlements of a directly assigned principal in a workspace. Changes are applied + * one at a time rather than atomically. If the request fails partway through, only some of the + * requested changes take effect. Get the assignment detail afterwards to confirm the final state. */ public WorkspaceAssignmentDetail updateWorkspaceAssignmentDetail( UpdateWorkspaceAssignmentDetailRequest request) { diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/AccountIamV2Service.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/AccountIamV2Service.java index d61010f20..29b276d34 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/AccountIamV2Service.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/AccountIamV2Service.java @@ -14,19 +14,18 @@ @Generated public interface AccountIamV2Service { /** - * Creates a workspace assignment detail for a principal. Entitlement grants are applied - * individually and non-atomically — if a failure occurs partway through, the principal will be - * assigned to the workspace but with only a subset of the requested entitlements. Use - * GetWorkspaceAssignmentDetail to confirm which entitlements were successfully granted. + * Creates a workspace assignment detail for a principal. Entitlements are granted one at a time + * rather than atomically. If the request fails partway through, the principal stays assigned to + * the workspace with only some of the requested entitlements. Get the assignment detail + * afterwards to confirm which entitlements were granted. */ WorkspaceAssignmentDetail createWorkspaceAssignmentDetail( CreateWorkspaceAssignmentDetailRequest createWorkspaceAssignmentDetailRequest); /** - * Deletes a workspace assignment detail for a principal, revoking all associated entitlements. - * Entitlement revocations are applied individually and non-atomically — if a failure occurs - * partway through, the principal remains assigned with a subset of its original entitlements, and - * the operation is safe to retry. + * Deletes a workspace assignment detail for a principal, revoking all of its entitlements. + * Entitlements are revoked one at a time rather than atomically. If the request fails partway + * through, the principal stays assigned with some of its original entitlements. Retrying is safe. */ void deleteWorkspaceAssignmentDetail( DeleteWorkspaceAssignmentDetailRequest deleteWorkspaceAssignmentDetailRequest); @@ -46,9 +45,9 @@ WorkspaceAssignmentDetail getWorkspaceAssignmentDetail( GetWorkspaceAssignmentDetailRequest getWorkspaceAssignmentDetailRequest); /** - * Lists workspace assignment details for a workspace. For scalability, the response omits the - * per-principal entitlement fields (`entitlements` and `effective_entitlements`); call - * GetWorkspaceAssignmentDetail to read entitlements for a single principal. + * Lists workspace assignment details for a workspace. The response omits the per-principal + * entitlement fields (`entitlements` and `effective_entitlements`). To read the entitlements for + * a single principal, get that principal's assignment detail. */ ListWorkspaceAssignmentDetailsResponse listWorkspaceAssignmentDetails( ListWorkspaceAssignmentDetailsRequest listWorkspaceAssignmentDetailsRequest); @@ -61,9 +60,9 @@ ListWorkspaceAssignmentDetailsResponse listWorkspaceAssignmentDetails( ResolveGroupResponse resolveGroup(ResolveGroupRequest resolveGroupRequest); /** - * Resolves an SP with the given external ID from the customer's IdP. If the SP does not exist, it - * will be created. If the customer is not onboarded onto Automatic Identity Management (AIM), - * this will return an error. + * Resolves a service principal with the given external ID from the customer's IdP. If the service + * principal does not exist, it will be created. If the customer is not onboarded onto Automatic + * Identity Management (AIM), this will return an error. */ ResolveServicePrincipalResponse resolveServicePrincipal( ResolveServicePrincipalRequest resolveServicePrincipalRequest); @@ -76,10 +75,9 @@ ResolveServicePrincipalResponse resolveServicePrincipal( ResolveUserResponse resolveUser(ResolveUserRequest resolveUserRequest); /** - * Updates the entitlements of a directly assigned principal in a workspace. Entitlement changes - * are applied individually and non-atomically — if a failure occurs partway through, only a - * subset of the requested changes may have been applied. Use GetWorkspaceAssignmentDetail to - * confirm the final state. + * Updates the entitlements of a directly assigned principal in a workspace. Changes are applied + * one at a time rather than atomically. If the request fails partway through, only some of the + * requested changes take effect. Get the assignment detail afterwards to confirm the final state. */ WorkspaceAssignmentDetail updateWorkspaceAssignmentDetail( UpdateWorkspaceAssignmentDetailRequest updateWorkspaceAssignmentDetailRequest); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ListWorkspaceAssignmentDetailsProxyRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ListWorkspaceAssignmentDetailsProxyRequest.java index 623e96482..2c1978f2e 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ListWorkspaceAssignmentDetailsProxyRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ListWorkspaceAssignmentDetailsProxyRequest.java @@ -18,10 +18,7 @@ public class ListWorkspaceAssignmentDetailsProxyRequest { @QueryParam("page_size") private Long pageSize; - /** - * A page token, received from a previous ListWorkspaceAssignmentDetailsProxy call. Provide this - * to retrieve the subsequent page. - */ + /** A page token from a previous list call. Provide this to retrieve the subsequent page. */ @JsonIgnore @QueryParam("page_token") private String pageToken; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveGroupProxyRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveGroupProxyRequest.java index f49573b95..f65165035 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveGroupProxyRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveGroupProxyRequest.java @@ -9,7 +9,7 @@ /** * Request message for resolving a group with the given external ID from the customer's IdP into - * Databricks. Will resolve metadata such as the group's groupname, and inherited parent groups. + * Databricks. Will resolve metadata such as the group's name and inherited parent groups. */ @Generated public class ResolveGroupProxyRequest { diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveGroupRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveGroupRequest.java index 2169e740a..fc8759e96 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveGroupRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveGroupRequest.java @@ -9,7 +9,7 @@ /** * Request message for resolving a group with the given external ID from the customer's IdP into - * Databricks. Will resolve metadata such as the group's groupname, and inherited parent groups. + * Databricks. Will resolve metadata such as the group's name and inherited parent groups. */ @Generated public class ResolveGroupRequest { diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveServicePrincipalProxyRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveServicePrincipalProxyRequest.java index 3f058b9cd..ff144b787 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveServicePrincipalProxyRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveServicePrincipalProxyRequest.java @@ -9,7 +9,7 @@ /** * Request message for resolving a service principal with the given external ID from the customer's - * IdP into Databricks. Will resolve metadata such as the service principal's displayname, status, + * IdP into Databricks. Will resolve metadata such as the service principal's display name, status, * and inherited parent groups. */ @Generated diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveServicePrincipalRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveServicePrincipalRequest.java index 84a647848..cd6ea6920 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveServicePrincipalRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveServicePrincipalRequest.java @@ -9,7 +9,7 @@ /** * Request message for resolving a service principal with the given external ID from the customer's - * IdP into Databricks. Will resolve metadata such as the service principal's displayname, status, + * IdP into Databricks. Will resolve metadata such as the service principal's display name, status, * and inherited parent groups. */ @Generated diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveUserProxyRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveUserProxyRequest.java index cda2a4f70..7c9f24442 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveUserProxyRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveUserProxyRequest.java @@ -9,7 +9,7 @@ /** * Request message for resolving a user with the given external ID from the customer's IdP into - * Databricks. Will resolve metadata such as the user's displayname, status, and inherited parent + * Databricks. Will resolve metadata such as the user's display name, status, and inherited parent * groups. */ @Generated diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveUserRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveUserRequest.java index bcca02a53..4d51b4c98 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveUserRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/ResolveUserRequest.java @@ -9,7 +9,7 @@ /** * Request message for resolving a user with the given external ID from the customer's IdP into - * Databricks. Will resolve metadata such as the user's displayname, status, and inherited parent + * Databricks. Will resolve metadata such as the user's display name, status, and inherited parent * groups. */ @Generated diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceAssignmentDetail.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceAssignmentDetail.java index 537e8d14c..f47ead207 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceAssignmentDetail.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceAssignmentDetail.java @@ -12,18 +12,19 @@ * The direct assignment of a provisioned account-level principal (user, service principal, or * group) to a workspace, together with the entitlements that assignment grants in the workspace. * - *

A WorkspaceAssignmentDetail exists only for principals that are directly assigned to the - * workspace; principals that merely inherit workspace access through a group are not represented - * here (see WorkspaceAccessDetail / WorkspaceIdentityDetail for the effective, direct-or-indirect - * view). Creating the resource assigns the principal to the workspace; deleting it removes the - * assignment. The `entitlements` field is the only client-settable field and defines the - * entitlements granted directly on this assignment; `effective_entitlements` is the read-only union - * of those plus any granted via group membership. + *

This resource covers only principals assigned directly to the workspace. Principals that + * inherit workspace access through a group are not represented here. See WorkspaceAccessDetail and + * WorkspaceIdentityDetail for the effective, direct-or-indirect view. Creating the resource assigns + * the principal to the workspace, and deleting it removes the assignment. * - *

A direct assignment always carries at least one directly-assigned entitlement: the assignment - * is what grants the entitlement, so a WorkspaceAssignmentDetail with an empty `entitlements` set - * is not a valid state. Both create and update require a non-empty `entitlements` set (an empty set - * is rejected); to remove a principal's assignment entirely, delete the resource. + *

`entitlements` is the only client-settable field. It holds the entitlements granted directly + * on this assignment, including any the principal also holds through a group. + * `effective_entitlements` is the read-only union of those and any granted through group + * membership. + * + *

A direct assignment always carries at least one directly-assigned entitlement, because the + * assignment is what grants it. Create and update both reject an empty `entitlements` set. To + * remove a principal's assignment entirely, delete the resource. * *

This resource replaces workspace assignment previously managed through the workspace SCIM and * permission-assignment APIs, and is intended for account and workspace admins. @@ -35,17 +36,17 @@ public class WorkspaceAssignmentDetail { private String accountId; /** - * The principal's full effective entitlements granted in this workspace: every entitlement it - * holds whether granted directly or via group membership. Populated on Get; empty on List. + * Every entitlement the principal holds in this workspace, whether granted directly or through + * group membership. Get responses populate this field. List responses leave it empty. */ @JsonProperty("effective_entitlements") private Collection effectiveEntitlements; /** - * Entitlements granted directly to the principal on this workspace. The only client-settable - * field: create and update manage exactly this set (including entitlements the principal also - * holds via a group). Not populated by ListWorkspaceAssignmentDetails (omitted for scalability); - * call GetWorkspaceAssignmentDetail to read the entitlements for a single principal. + * Entitlements granted directly to the principal on this workspace. This is the only + * client-settable field. Create and update manage exactly this set, including entitlements the + * principal also holds through a group. List responses leave this field empty. Get a single + * principal to read its entitlements. */ @JsonProperty("entitlements") private Collection entitlements; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceIamV2API.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceIamV2API.java index 092608d8e..df2a09488 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceIamV2API.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceIamV2API.java @@ -27,11 +27,10 @@ public WorkspaceIamV2API(WorkspaceIamV2Service mock) { } /** - * Creates a workspace assignment detail for a principal (workspace-level proxy). Entitlement - * grants are applied individually and non-atomically — if a failure occurs partway through, the - * principal will be assigned to the workspace but with only a subset of the requested - * entitlements. Use GetWorkspaceAssignmentDetail to confirm which entitlements were successfully - * granted. + * Creates a workspace assignment detail for a principal in the calling workspace. Entitlements + * are granted one at a time rather than atomically. If the request fails partway through, the + * principal stays assigned to the workspace with only some of the requested entitlements. Get the + * assignment detail afterwards to confirm which entitlements were granted. */ public WorkspaceAssignmentDetail createWorkspaceAssignmentDetailProxy( CreateWorkspaceAssignmentDetailProxyRequest request) { @@ -44,10 +43,10 @@ public void deleteWorkspaceAssignmentDetailProxy(long principalId) { } /** - * Deletes a workspace assignment detail for a principal (workspace-level proxy), revoking all - * associated entitlements. Entitlement revocations are applied individually and non-atomically — - * if a failure occurs partway through, the principal remains assigned with a subset of its - * original entitlements, and the operation is safe to retry. + * Deletes a workspace assignment detail for a principal in the calling workspace, revoking all of + * its entitlements. Entitlements are revoked one at a time rather than atomically. If the request + * fails partway through, the principal stays assigned with some of its original entitlements. + * Retrying is safe. */ public void deleteWorkspaceAssignmentDetailProxy( DeleteWorkspaceAssignmentDetailProxyRequest request) { @@ -76,17 +75,16 @@ public WorkspaceAssignmentDetail getWorkspaceAssignmentDetailProxy(long principa new GetWorkspaceAssignmentDetailProxyRequest().setPrincipalId(principalId)); } - /** Returns the assignment details for a principal in a workspace (workspace-level proxy). */ + /** Returns the assignment details for a principal in the calling workspace. */ public WorkspaceAssignmentDetail getWorkspaceAssignmentDetailProxy( GetWorkspaceAssignmentDetailProxyRequest request) { return impl.getWorkspaceAssignmentDetailProxy(request); } /** - * Lists workspace assignment details for a workspace (workspace-level proxy). For scalability, - * the response omits the per-principal entitlement fields (`entitlements` and - * `effective_entitlements`); call GetWorkspaceAssignmentDetailProxy to read entitlements for a - * single principal. + * Lists workspace assignment details for the calling workspace. The response omits the + * per-principal entitlement fields (`entitlements` and `effective_entitlements`). To read the + * entitlements for a single principal, get that principal's assignment detail. */ public ListWorkspaceAssignmentDetailsResponse listWorkspaceAssignmentDetailsProxy( ListWorkspaceAssignmentDetailsProxyRequest request) { @@ -103,9 +101,9 @@ public ResolveGroupResponse resolveGroupProxy(ResolveGroupProxyRequest request) } /** - * Resolves an SP with the given external ID from the customer's IdP. If the SP does not exist, it - * will be created. If the customer is not onboarded onto Automatic Identity Management (AIM), - * this will return an error. + * Resolves a service principal with the given external ID from the customer's IdP. If the service + * principal does not exist, it will be created. If the customer is not onboarded onto Automatic + * Identity Management (AIM), this will return an error. */ public ResolveServicePrincipalResponse resolveServicePrincipalProxy( ResolveServicePrincipalProxyRequest request) { @@ -122,10 +120,10 @@ public ResolveUserResponse resolveUserProxy(ResolveUserProxyRequest request) { } /** - * Updates the entitlements of a directly assigned principal in a workspace (workspace-level - * proxy). Entitlement changes are applied individually and non-atomically — if a failure occurs - * partway through, only a subset of the requested changes may have been applied. Use - * GetWorkspaceAssignmentDetail to confirm the final state. + * Updates the entitlements of a directly assigned principal in the calling workspace. Changes are + * applied one at a time rather than atomically. If the request fails partway through, only some + * of the requested changes take effect. Get the assignment detail afterwards to confirm the final + * state. */ public WorkspaceAssignmentDetail updateWorkspaceAssignmentDetailProxy( UpdateWorkspaceAssignmentDetailProxyRequest request) { diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceIamV2Service.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceIamV2Service.java index 1d9551c5d..289bda051 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceIamV2Service.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/iamv2/WorkspaceIamV2Service.java @@ -14,20 +14,19 @@ @Generated public interface WorkspaceIamV2Service { /** - * Creates a workspace assignment detail for a principal (workspace-level proxy). Entitlement - * grants are applied individually and non-atomically — if a failure occurs partway through, the - * principal will be assigned to the workspace but with only a subset of the requested - * entitlements. Use GetWorkspaceAssignmentDetail to confirm which entitlements were successfully - * granted. + * Creates a workspace assignment detail for a principal in the calling workspace. Entitlements + * are granted one at a time rather than atomically. If the request fails partway through, the + * principal stays assigned to the workspace with only some of the requested entitlements. Get the + * assignment detail afterwards to confirm which entitlements were granted. */ WorkspaceAssignmentDetail createWorkspaceAssignmentDetailProxy( CreateWorkspaceAssignmentDetailProxyRequest createWorkspaceAssignmentDetailProxyRequest); /** - * Deletes a workspace assignment detail for a principal (workspace-level proxy), revoking all - * associated entitlements. Entitlement revocations are applied individually and non-atomically — - * if a failure occurs partway through, the principal remains assigned with a subset of its - * original entitlements, and the operation is safe to retry. + * Deletes a workspace assignment detail for a principal in the calling workspace, revoking all of + * its entitlements. Entitlements are revoked one at a time rather than atomically. If the request + * fails partway through, the principal stays assigned with some of its original entitlements. + * Retrying is safe. */ void deleteWorkspaceAssignmentDetailProxy( DeleteWorkspaceAssignmentDetailProxyRequest deleteWorkspaceAssignmentDetailProxyRequest); @@ -42,15 +41,14 @@ void deleteWorkspaceAssignmentDetailProxy( WorkspaceAccessDetail getWorkspaceAccessDetailLocal( GetWorkspaceAccessDetailLocalRequest getWorkspaceAccessDetailLocalRequest); - /** Returns the assignment details for a principal in a workspace (workspace-level proxy). */ + /** Returns the assignment details for a principal in the calling workspace. */ WorkspaceAssignmentDetail getWorkspaceAssignmentDetailProxy( GetWorkspaceAssignmentDetailProxyRequest getWorkspaceAssignmentDetailProxyRequest); /** - * Lists workspace assignment details for a workspace (workspace-level proxy). For scalability, - * the response omits the per-principal entitlement fields (`entitlements` and - * `effective_entitlements`); call GetWorkspaceAssignmentDetailProxy to read entitlements for a - * single principal. + * Lists workspace assignment details for the calling workspace. The response omits the + * per-principal entitlement fields (`entitlements` and `effective_entitlements`). To read the + * entitlements for a single principal, get that principal's assignment detail. */ ListWorkspaceAssignmentDetailsResponse listWorkspaceAssignmentDetailsProxy( ListWorkspaceAssignmentDetailsProxyRequest listWorkspaceAssignmentDetailsProxyRequest); @@ -63,9 +61,9 @@ ListWorkspaceAssignmentDetailsResponse listWorkspaceAssignmentDetailsProxy( ResolveGroupResponse resolveGroupProxy(ResolveGroupProxyRequest resolveGroupProxyRequest); /** - * Resolves an SP with the given external ID from the customer's IdP. If the SP does not exist, it - * will be created. If the customer is not onboarded onto Automatic Identity Management (AIM), - * this will return an error. + * Resolves a service principal with the given external ID from the customer's IdP. If the service + * principal does not exist, it will be created. If the customer is not onboarded onto Automatic + * Identity Management (AIM), this will return an error. */ ResolveServicePrincipalResponse resolveServicePrincipalProxy( ResolveServicePrincipalProxyRequest resolveServicePrincipalProxyRequest); @@ -78,10 +76,10 @@ ResolveServicePrincipalResponse resolveServicePrincipalProxy( ResolveUserResponse resolveUserProxy(ResolveUserProxyRequest resolveUserProxyRequest); /** - * Updates the entitlements of a directly assigned principal in a workspace (workspace-level - * proxy). Entitlement changes are applied individually and non-atomically — if a failure occurs - * partway through, only a subset of the requested changes may have been applied. Use - * GetWorkspaceAssignmentDetail to confirm the final state. + * Updates the entitlements of a directly assigned principal in the calling workspace. Changes are + * applied one at a time rather than atomically. If the request fails partway through, only some + * of the requested changes take effect. Get the assignment detail afterwards to confirm the final + * state. */ WorkspaceAssignmentDetail updateWorkspaceAssignmentDetailProxy( UpdateWorkspaceAssignmentDetailProxyRequest updateWorkspaceAssignmentDetailProxyRequest); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/JobsAPI.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/JobsAPI.java index d4125be6e..fb29d03f0 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/JobsAPI.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/JobsAPI.java @@ -244,7 +244,10 @@ public Iterable list(ListJobsRequest request) { }); } - /** List runs in descending order by start time. */ + /** + * List runs in descending order by end time. If a run has not finished, it falls back to start + * time. + */ public Iterable listRuns(ListRunsRequest request) { return Paginator.newTokenPagination( request, diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/JobsService.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/JobsService.java index fc317fde5..38ece5467 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/JobsService.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/JobsService.java @@ -101,7 +101,10 @@ GetJobPermissionLevelsResponse getPermissionLevels( /** Retrieves a list of jobs. */ ListJobsResponse list(ListJobsRequest listJobsRequest); - /** List runs in descending order by start time. */ + /** + * List runs in descending order by end time. If a run has not finished, it falls back to start + * time. + */ ListRunsResponse listRuns(ListRunsRequest listRunsRequest); /** diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/RunNow.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/RunNow.java index 980c7ab30..09f7343ac 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/RunNow.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/RunNow.java @@ -32,10 +32,6 @@ public class RunNow { * Databricks guarantees that exactly one run is launched with that idempotency token. * *

This token must have at most 64 characters. - * - *

For more information, see [How to ensure idempotency for jobs]. - * - *

[How to ensure idempotency for jobs]: https://kb.databricks.com/jobs/jobs-idempotency.html */ @JsonProperty("idempotency_token") private String idempotencyToken; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SubmitRun.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SubmitRun.java index bf8cec57b..7793d8ad7 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SubmitRun.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/jobs/SubmitRun.java @@ -60,10 +60,6 @@ public class SubmitRun { * Databricks guarantees that exactly one run is launched with that idempotency token. * *

This token must have at most 64 characters. - * - *

For more information, see [How to ensure idempotency for jobs]. - * - *

[How to ensure idempotency for jobs]: https://kb.databricks.com/jobs/jobs-idempotency.html */ @JsonProperty("idempotency_token") private String idempotencyToken; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/KinesisStreamConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/KinesisStreamConfig.java new file mode 100644 index 000000000..7c5a5d92d --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/KinesisStreamConfig.java @@ -0,0 +1,83 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; +import com.databricks.sdk.support.ToStringer; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; +import java.util.Objects; + +/** + * Kinesis-specific configuration for a Stream. For the underlying connector and its source options, + * see the Databricks documentation on connecting to Amazon Kinesis + * (https://docs.databricks.com/aws/en/connect/streaming/kinesis). + */ +@Generated +public class KinesisStreamConfig { + /** + * Optional Kinesis source options, validated against a server-side allowlist at request time. + * Auth and connection details belong on the parent Stream's `connection_config`, not here. + */ + @JsonProperty("extra_options") + private Map extraOptions; + + /** Kinesis stream ARNs to read from. */ + @JsonProperty("stream_arns") + private StreamArnList streamArns; + + /** Kinesis stream names to read from. */ + @JsonProperty("stream_names") + private StreamNameList streamNames; + + public KinesisStreamConfig setExtraOptions(Map extraOptions) { + this.extraOptions = extraOptions; + return this; + } + + public Map getExtraOptions() { + return extraOptions; + } + + public KinesisStreamConfig setStreamArns(StreamArnList streamArns) { + this.streamArns = streamArns; + return this; + } + + public StreamArnList getStreamArns() { + return streamArns; + } + + public KinesisStreamConfig setStreamNames(StreamNameList streamNames) { + this.streamNames = streamNames; + return this; + } + + public StreamNameList getStreamNames() { + return streamNames; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + KinesisStreamConfig that = (KinesisStreamConfig) o; + return Objects.equals(extraOptions, that.extraOptions) + && Objects.equals(streamArns, that.streamArns) + && Objects.equals(streamNames, that.streamNames); + } + + @Override + public int hashCode() { + return Objects.hash(extraOptions, streamArns, streamNames); + } + + @Override + public String toString() { + return new ToStringer(KinesisStreamConfig.class) + .add("extraOptions", extraOptions) + .add("streamArns", streamArns) + .add("streamNames", streamNames) + .toString(); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamArnList.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamArnList.java new file mode 100644 index 000000000..f6ceb4d1f --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamArnList.java @@ -0,0 +1,47 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; +import com.databricks.sdk.support.ToStringer; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collection; +import java.util.Objects; + +/** A list of Kinesis stream ARNs to read from. */ +@Generated +public class StreamArnList { + /** + * Kinesis stream ARNs to read from. For example, + * 'arn:aws:kinesis:us-west-2:111122223333:stream/stream-a'. + */ + @JsonProperty("arns") + private Collection arns; + + public StreamArnList setArns(Collection arns) { + this.arns = arns; + return this; + } + + public Collection getArns() { + return arns; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StreamArnList that = (StreamArnList) o; + return Objects.equals(arns, that.arns); + } + + @Override + public int hashCode() { + return Objects.hash(arns); + } + + @Override + public String toString() { + return new ToStringer(StreamArnList.class).add("arns", arns).toString(); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamNameList.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamNameList.java new file mode 100644 index 000000000..b5b9790c8 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamNameList.java @@ -0,0 +1,44 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; +import com.databricks.sdk.support.ToStringer; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collection; +import java.util.Objects; + +/** A list of Kinesis stream names to read from. */ +@Generated +public class StreamNameList { + /** Kinesis stream names to read from. */ + @JsonProperty("names") + private Collection names; + + public StreamNameList setNames(Collection names) { + this.names = names; + return this; + } + + public Collection getNames() { + return names; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StreamNameList that = (StreamNameList) o; + return Objects.equals(names, that.names); + } + + @Override + public int hashCode() { + return Objects.hash(names); + } + + @Override + public String toString() { + return new ToStringer(StreamNameList.class).add("names", names).toString(); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamSourceConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamSourceConfig.java index b1b8ec234..9d95af7ea 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamSourceConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/StreamSourceConfig.java @@ -14,6 +14,10 @@ public class StreamSourceConfig { @JsonProperty("kafka_stream_config") private KafkaStreamConfig kafkaStreamConfig; + /** Configuration for AWS Kinesis Data Streams. */ + @JsonProperty("kinesis_stream_config") + private KinesisStreamConfig kinesisStreamConfig; + public StreamSourceConfig setKafkaStreamConfig(KafkaStreamConfig kafkaStreamConfig) { this.kafkaStreamConfig = kafkaStreamConfig; return this; @@ -23,23 +27,34 @@ public KafkaStreamConfig getKafkaStreamConfig() { return kafkaStreamConfig; } + public StreamSourceConfig setKinesisStreamConfig(KinesisStreamConfig kinesisStreamConfig) { + this.kinesisStreamConfig = kinesisStreamConfig; + return this; + } + + public KinesisStreamConfig getKinesisStreamConfig() { + return kinesisStreamConfig; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; StreamSourceConfig that = (StreamSourceConfig) o; - return Objects.equals(kafkaStreamConfig, that.kafkaStreamConfig); + return Objects.equals(kafkaStreamConfig, that.kafkaStreamConfig) + && Objects.equals(kinesisStreamConfig, that.kinesisStreamConfig); } @Override public int hashCode() { - return Objects.hash(kafkaStreamConfig); + return Objects.hash(kafkaStreamConfig, kinesisStreamConfig); } @Override public String toString() { return new ToStringer(StreamSourceConfig.class) .add("kafkaStreamConfig", kafkaStreamConfig) + .add("kinesisStreamConfig", kinesisStreamConfig) .toString(); } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java index ffc007fed..9f67fdcf1 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateInfo.java @@ -42,6 +42,13 @@ public class UpdateInfo { @JsonProperty("full_refresh_selection") private Collection fullRefreshSelection; + /** + * Indicates whether the update is either part of a continuous job run, or running in legacy + * continuous pipeline mode. Returned only for GetUpdate; not populated in ListUpdates responses. + */ + @JsonProperty("mode") + private UpdateMode mode; + /** Key/value map of parameters used to initiate the update */ @JsonProperty("parameters") private Map parameters; @@ -127,6 +134,15 @@ public Collection getFullRefreshSelection() { return fullRefreshSelection; } + public UpdateInfo setMode(UpdateMode mode) { + this.mode = mode; + return this; + } + + public UpdateMode getMode() { + return mode; + } + public UpdateInfo setParameters(Map parameters) { this.parameters = parameters; return this; @@ -192,6 +208,7 @@ public boolean equals(Object o) { && Objects.equals(creationTime, that.creationTime) && Objects.equals(fullRefresh, that.fullRefresh) && Objects.equals(fullRefreshSelection, that.fullRefreshSelection) + && Objects.equals(mode, that.mode) && Objects.equals(parameters, that.parameters) && Objects.equals(pipelineId, that.pipelineId) && Objects.equals(refreshSelection, that.refreshSelection) @@ -209,6 +226,7 @@ public int hashCode() { creationTime, fullRefresh, fullRefreshSelection, + mode, parameters, pipelineId, refreshSelection, @@ -226,6 +244,7 @@ public String toString() { .add("creationTime", creationTime) .add("fullRefresh", fullRefresh) .add("fullRefreshSelection", fullRefreshSelection) + .add("mode", mode) .add("parameters", parameters) .add("pipelineId", pipelineId) .add("refreshSelection", refreshSelection) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateMode.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateMode.java new file mode 100644 index 000000000..752421818 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/pipelines/UpdateMode.java @@ -0,0 +1,11 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.pipelines; + +import com.databricks.sdk.support.Generated; + +@Generated +public enum UpdateMode { + CONTINUOUS, + DEFAULT, +} diff --git a/tagging.py b/tagging.py index 3a75f3728..e887a7144 100644 --- a/tagging.py +++ b/tagging.py @@ -18,6 +18,26 @@ PACKAGE_FILE_NAME = ".package.json" CODEGEN_FILE_NAME = ".codegen.json" CREATED_TAGS_FILE_NAME = "created_tags.json" + +# Presence of this env var switches the changelog source from a single +# hand-maintained ``NEXT_CHANGELOG.md`` to per-PR ``

/
/*.md`` +# fragments, and the release version from the ``## Release vX.Y.Z`` header to a +# ``/version`` file. Its value is the fragment directory name (e.g. +# ``.nextchanges``). Unset for every SDK repo, so their behavior is unchanged; +# a repo opts in by setting it in the tagging workflow (see the databricks/cli +# release workflow). The per-section ``(slug, header)`` mapping is read from +# ``.codegen.json``'s ``nextchanges_sections`` key. +NEXTCHANGES_DIR_ENV = "NEXTCHANGES_DIR" + +# File inside the fragment directory tracking the next release's version — +# read at release time and bumped afterward, the role the ``## Release vX.Y.Z`` +# header plays in the ``NEXT_CHANGELOG.md`` flow. +NEXTCHANGES_VERSION_FILE = "version" + +# ``README.md`` in a section slug is documentation (e.g. "put CLI changelog +# fragments here"), not a changelog fragment. It is excluded from rendering and +# preserved across releases, so teams can keep per-slug guidance in place. +NEXTCHANGES_README_FILE = "README.md" """ This script tags the release of the SDKs using a combination of the GitHub API and Git commands. It reads the local repository to determine necessary changes, updates changelogs, and creates tags. @@ -466,23 +486,214 @@ def get_previous_tag_info(package: Package) -> Optional[TagInfo]: return TagInfo(package=package, version=version, content=latest_release) -def _load_codegen_config() -> Dict: +def _load_codegen_config(package_path: str = "") -> Dict: """ - Loads ``.codegen.json`` from the repo root. Returns an empty dict when - the file is missing. + Loads ``.codegen.json`` for a package: prefers ``/.codegen.json`` + and falls back to the repo-root file, returning an empty dict when neither + exists. ``package_path=""`` (the default) reads the repo root, matching the + single-package / root-config layout. + + Package-local lookup keeps the section taxonomy and other codegen options in + lockstep with the package-relative directories the nextchanges helpers + resolve, so a multi-package repo can give each package its own config + instead of every package sharing the root file. """ - package_file_path = os.path.join(os.getcwd(), CODEGEN_FILE_NAME) - if not os.path.exists(package_file_path): - return {} - with open(package_file_path, "r") as file: - return json.load(file) + candidates = [os.path.join(os.getcwd(), package_path, CODEGEN_FILE_NAME)] + root_config = os.path.join(os.getcwd(), CODEGEN_FILE_NAME) + if root_config not in candidates: + candidates.append(root_config) + for candidate in candidates: + if os.path.exists(candidate): + with open(candidate, "r") as file: + return json.load(file) + return {} + + +def _nextchanges_dir() -> Optional[str]: + """ + Returns the fragment directory name when nextchanges mode is enabled + (``NEXTCHANGES_DIR`` set to a non-empty value), else ``None``. In the + ``None`` case the historical ``NEXT_CHANGELOG.md`` flow is used, so every + repo that doesn't set the env var is unaffected. + """ + return os.environ.get(NEXTCHANGES_DIR_ENV, "").strip() or None + + +def _nextchanges_sections(package_path: str = "") -> List[tuple]: + """ + Returns the ordered ``(slug, header)`` section list from the package's + ``.codegen.json`` ``nextchanges_sections`` — the mapping of ``//`` + subdirectories to the ``###
`` blocks they render into, in changelog + order. Read via ``_load_codegen_config(package_path)`` so it matches the + package-relative fragment directories (a multi-package repo can scope the + taxonomy per package). + + Declared as a JSON object ``{"": "
", ...}`` so the per-repo + section taxonomy stays out of this shared script; insertion order in the + object is the changelog order (JSON objects preserve order in Python 3.7+). + Raises when nextchanges mode is on but the key is absent/empty, or is not an + object, since there would be nothing sensible to render. + """ + sections = _load_codegen_config(package_path).get("nextchanges_sections", {}) + if not sections: + raise Exception( + f"nextchanges mode is enabled ({NEXTCHANGES_DIR_ENV} set) but " + f"`nextchanges_sections` is missing or empty in {CODEGEN_FILE_NAME}." + ) + if not isinstance(sections, dict): + raise Exception( + f"`nextchanges_sections` in {CODEGEN_FILE_NAME} must be a JSON object " + f'mapping section slug to header (e.g. {{"cli": "CLI"}}), got ' + f"{type(sections).__name__}." + ) + return list(sections.items()) + + +def _render_fragment(text: str) -> str: + """ + Render one fragment body into changelog bullets. Each line that starts with + a ``* ``/``- `` marker (ignoring leading whitespace) becomes its own `` * `` + bullet; a line without a marker is a continuation of the preceding bullet + and is kept as authored. A markerless first line is itself a single bullet. + + So a fragment with multiple ``* ``/``- `` lines renders as multiple bullets, + while a bullet followed by plain lines stays one bullet spanning those + lines. Every bullet gets the leading-space ``*`` that matches CHANGELOG.md. + """ + lines = [] + for line in text.split("\n"): + marker = line.lstrip() + if marker.startswith(("* ", "- ")): + lines.append(f" * {marker[2:]}") + elif lines: + lines.append(line) + else: + lines.append(f" * {line}") + return "\n".join(lines) + + +def render_nextchanges(package_path: str) -> Optional[str]: + """ + Render ``//
/*.md`` fragments into the changelog + body: one ``###
`` block per non-empty section in + ``nextchanges_sections`` order, fragments sorted by filename. Returns + ``None`` when there are no fragments. + + Every ``.md`` file under a section directory is a fragment, except + ``README.md`` which is treated as per-slug documentation and skipped (see + ``NEXTCHANGES_README_FILE``). Empty/whitespace-only files contribute + nothing. Files at the ```` root or under a slug not listed in + ``nextchanges_sections`` are ignored. Each fragment renders per + ``_render_fragment``. Link expansion (e.g. ``(#1234)`` → markdown link) is + assumed to have happened before release, so none here. + """ + base = os.path.join(os.getcwd(), package_path, _nextchanges_dir()) + if not os.path.isdir(base): + return None + + blocks = [] + for slug, header in _nextchanges_sections(package_path): + section_dir = os.path.join(base, slug) + if not os.path.isdir(section_dir): + continue + entries = [] + for name in sorted(os.listdir(section_dir)): + if not name.endswith(".md") or name == NEXTCHANGES_README_FILE: + continue + with open(os.path.join(section_dir, name)) as f: + text = f.read().strip() + if not text: + continue + entries.append(_render_fragment(text)) + if entries: + # Blank line after the heading, matching CHANGELOG.md. + blocks.append(f"### {header}\n\n" + "\n".join(entries)) + + if not blocks: + return None + return "\n\n".join(blocks) + + +def _nextchanges_version_path(package_path: str) -> str: + return os.path.join(os.getcwd(), package_path, _nextchanges_dir(), NEXTCHANGES_VERSION_FILE) + + +def read_nextchanges_version(package: Package) -> str: + """ + Release version for this run, read from the package's own ``/version`` + (resolved under ``package.path``, so each package in a multi-package repo + keeps its own version source). In nextchanges mode this file — not the + ``## Release v…`` changelog header — is the source of truth. To cut a patch + or major release, edit it in the PR; otherwise its default (bumped to the + next minor after the previous release by ``clean_nextchanges``) applies. + + Raises with an actionable message when the file is absent, so a package that + opts into nextchanges mode without a version file fails loudly instead of + with a bare ``FileNotFoundError``. + """ + version_path = _nextchanges_version_path(package.path) + if not os.path.exists(version_path): + raise Exception( + f"nextchanges mode is enabled ({NEXTCHANGES_DIR_ENV} set) but the version " + f"file {os.path.relpath(version_path, os.getcwd())} is missing; each package " + f"in nextchanges mode must provide its own /version file." + ) + with open(version_path) as f: + return str(Version.parse(f.read().strip().lstrip("v"))) + + +def get_next_tag_info_from_nextchanges(package: Package) -> Optional[TagInfo]: + """ + nextchanges-mode counterpart of ``get_next_tag_info``: build the release + TagInfo from ``/`` fragments. Returns ``None`` when there are no + entries (nothing to release), unless ``allow_empty_changelog`` is set in + ``.codegen.json`` — matching the ``NEXT_CHANGELOG.md`` skip behavior. + """ + body = render_nextchanges(package.path) + if body is None and not _load_codegen_config(package.path).get("allow_empty_changelog", False): + print(f"No {_nextchanges_dir()}/ entries. No changes will be made to the changelog.") + return None + + version = read_nextchanges_version(package) + # write_changelog() keys off the "## Release v…" header, so include it. + content = f"## Release v{version}\n" + (f"\n{body}\n" if body else "") + return TagInfo(package=package, version=version, content=content) + + +def clean_nextchanges(package_path: str) -> None: + """ + nextchanges-mode counterpart of ``clean_next_changelog``: stage deletion of + the ``/`` fragments consumed by this release and bump ``/version`` + to the next minor (its post-release default; teams can still override it in + a PR). Deletes every ``.md`` under each section directory — the same set + ``render_nextchanges`` consumed, so ``README.md`` is preserved — leaving the + section directories in place. + """ + base = os.path.join(os.getcwd(), package_path, _nextchanges_dir()) + for slug, _ in _nextchanges_sections(package_path): + section_dir = os.path.join(base, slug) + if not os.path.isdir(section_dir): + continue + # Deletion order is irrelevant, so listdir as-is (no sort needed). + for name in os.listdir(section_dir): + if name.endswith(".md") and name != NEXTCHANGES_README_FILE: + gh.delete_file(os.path.join(section_dir, name)) + + version_path = _nextchanges_version_path(package_path) + with open(version_path) as f: + released = Version.parse(f.read().strip().lstrip("v")) + gh.add_file(version_path, f"{released.next_release_version()}\n") def get_next_tag_info(package: Package) -> Optional[TagInfo]: """ - Extracts the changes from the "NEXT_CHANGELOG.md" file. - The result is already processed. + Extracts the changes for the next release. In nextchanges mode (see + ``_nextchanges_dir``) it reads ``/`` fragments; otherwise it reads the + package's ``NEXT_CHANGELOG.md``. The result is already processed. """ + if _nextchanges_dir() is not None: + return get_next_tag_info_from_nextchanges(package) + next_changelog_path = os.path.join(os.getcwd(), package.path, NEXT_CHANGELOG_FILE_NAME) # Read NEXT_CHANGELOG.md with open(next_changelog_path, "r") as f: @@ -500,7 +711,9 @@ def get_next_tag_info(package: Package) -> Optional[TagInfo]: # sections are skipped — there's nothing meaningful to release. # Repos like sdk-js which are still in development can opt in # by setting ``allow_empty_changelog: true`` in .codegen.json. - if not re.search(r"###", next_changelog) and not _load_codegen_config().get("allow_empty_changelog", False): + if not re.search(r"###", next_changelog) and not _load_codegen_config(package.path).get( + "allow_empty_changelog", False + ): print("All sections are empty. No changes will be made to the changelog.") return None @@ -546,7 +759,10 @@ def process_package(package: Package) -> TagInfo: return write_changelog(tag_info) - clean_next_changelog(package.path) + if _nextchanges_dir() is not None: + clean_nextchanges(package.path) + else: + clean_next_changelog(package.path) return tag_info @@ -984,15 +1200,11 @@ def pull_last_release_commit() -> None: reset_repository(commit_hash) -def get_packages_from_args() -> List[str]: +def _build_arg_parser() -> argparse.ArgumentParser: """ - Retrieves the list of packages to tag. - - python3 ./tagging.py --package # single package - python3 ./tagging.py --package , # multiple packages - - Returns an empty list when --package is omitted, which means all packages - with pending releases will be tagged. + Builds the CLI parser. Shared by ``get_packages_from_args`` and + ``args_request_preview`` so both accept the same flags — parsing either one + with an unknown flag present would otherwise error. """ parser = argparse.ArgumentParser(description="Update changelogs and tag the release.") parser.add_argument( @@ -1002,10 +1214,78 @@ def get_packages_from_args() -> List[str]: default="", help="Comma-separated list of packages to tag. Leave empty to tag all packages with pending releases.", ) - args = parser.parse_args() + parser.add_argument( + "--preview", + action="store_true", + help=( + "Print the changelog section the next release would add, then exit " + "(no writes, no network). Only supported in nextchanges mode." + ), + ) + return parser + + +def get_packages_from_args() -> List[str]: + """ + Retrieves the list of packages to tag. + + python3 ./tagging.py --package # single package + python3 ./tagging.py --package , # multiple packages + + Returns an empty list when --package is omitted, which means all packages + with pending releases will be tagged. + """ + args = _build_arg_parser().parse_args() return [name.strip() for name in args.package.split(",") if name.strip()] +def _select_packages(all_packages: List[Package]) -> List[Package]: + """ + Narrow ``all_packages`` to the ``--package`` selection, or return all of + them when ``--package`` is omitted. Shared by ``process`` and ``preview`` so + the read-only preview covers exactly the release scope the same CLI + arguments would execute — ``tagging.py --package foo --preview`` previews + only ``foo``, not every package in the repo. + """ + package_names = get_packages_from_args() + if not package_names: + return all_packages + return [package for package in all_packages if package.name in package_names] + + +def args_request_preview() -> bool: + """Returns whether ``--preview`` was passed.""" + return _build_arg_parser().parse_args().preview + + +def preview() -> None: + """ + Print the ``## Release vX.Y.Z`` section(s) the next release would prepend to + CHANGELOG.md, rendered from the current ``/`` fragments — without + touching git, GitHub, or any file. Mirrors ``write_changelog``'s date stamp + so the output matches what would land. Read-only: safe to run anytime, no + credentials. Only meaningful in nextchanges mode. + """ + if _nextchanges_dir() is None: + raise Exception(f"--preview requires nextchanges mode ({NEXTCHANGES_DIR_ENV} must be set).") + + current_date = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d") + printed = False + for package in _select_packages(find_packages()): + tag_info = get_next_tag_info(package) + if tag_info is None: + continue + dated = re.sub( + rf"## Release v({Version.PATTERN})", + rf"## Release v\1 ({current_date})", + tag_info.content.strip(), + ) + print(dated) + printed = True + if not printed: + print(f"No {_nextchanges_dir()}/ entries — the next release would add no changelog section.") + + def init_github(): token = os.environ["GITHUB_TOKEN"] repo_name = os.environ["GITHUB_REPOSITORY"] @@ -1048,10 +1328,8 @@ def process(): all_packages = find_packages() # If packages are specified as an argument, only release those — but # dep rewrites and the freshness check still operate over the full - # set. - selected_packages = all_packages - if package_names: - selected_packages = [package for package in all_packages if package.name in package_names] + # set. Shared with preview() so both scope identically. + selected_packages = _select_packages(all_packages) # Run the freshness check against a read-only preview before the # retry loop, since the check is deterministic. A freshness @@ -1078,6 +1356,10 @@ def validate_git_root(): def main(): validate_git_root() + # Preview is read-only: no GitHub credentials, no network, no commits. + if args_request_preview(): + preview() + return init_github() process()