Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add @InternalApi to binary compatibility checks; introduce new PR check to verify no API-breaking changes #1030

Merged
merged 6 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/api-compat-verification.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: API compatibility verification

on:
pull_request:
types: [ opened, synchronize, reopened, labeled, unlabeled ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason to specify these types? Our other workflows look like they apply to all types

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied the job definition from changelog-verification.yml which also explicitly specifies PR events. I think, in general, we could be more conservative in the subtypes of events which trigger action runs and reduce some of the churn/cost associated with them.

Do you have a reason to prefer running on all event subtypes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No actually, I think the current types cover all the cases where this should run, so it's good to leave it as is. I just never saw these types specified (I did not look at the changelog-verification.yml job) and was curious

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice for us these are likely about the same but it's fine as is, here is the full list for reference if you leave it unspecified and just have pull_request:

branches: [ main ]

jobs:
api-compat-verification:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check for API compatibility
if: ${{ !contains(github.event.pull_request.labels.*.name, 'acknowledge-api-break') }}
run: |
git fetch origin ${{ github.base_ref }} --depth 1 && \
git diff remotes/origin/${{ github.base_ref }} --numstat "*.api" | awk '
BEGIN { s = 0 }

# git diff numstat shows lines deleted in field 2, hence sum up field 2 across all items
{ s += $2 }

# exit with the number of lines deleted as the result code so that `if failure()` works below
END { exit s }
'
- name: Error message
if: ${{ failure() }}
run: |
echo "::error ::This change modifies the public API in a way that may be backwards-incompatible. Carefully review this pull request and either:"
echo "::error ::* Revert the changes which caused the API incompatibility –or–"
echo "::error ::* Add the 'acknowledge-api-break' label to this PR (in rare cases warranting an API breakage)"
exit 1
2 changes: 0 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,6 @@ configureLinting(lintPaths)

// Binary compatibility
apiValidation {
nonPublicMarkers.add("aws.smithy.kotlin.runtime.InternalApi")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I agree with this change but I am wondering about what we will do when we do need/want to break internal APIs. Presumably we'd deprecate the APIs and leave them in place for some period of time or perhaps indefinitely and switch codegen to use whatever the replacement is?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline and decided largely on what @aajtodd suggested: if we need to deprecate an @InternalApi declaration, we'll mark the API as @Deprecated and leave it in place for some number of releases. It will be considered for (potentially-breaking) removal if it is determined to be actively harming something (e.g., security, critical bugs, etc.).


ignoredProjects.addAll(
setOf(
"dokka-smithy",
Expand Down
41 changes: 41 additions & 0 deletions runtime/auth/aws-signing-common/api/aws-signing-common.api
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
public final class aws/smithy/kotlin/runtime/auth/awssigning/AwsChunkedByteReadChannel : aws/smithy/kotlin/runtime/io/SdkByteReadChannel {
public fun <init> (Laws/smithy/kotlin/runtime/io/SdkByteReadChannel;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigner;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig;[BLaws/smithy/kotlin/runtime/http/DeferredHeaders;)V
public synthetic fun <init> (Laws/smithy/kotlin/runtime/io/SdkByteReadChannel;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigner;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig;[BLaws/smithy/kotlin/runtime/http/DeferredHeaders;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun cancel (Ljava/lang/Throwable;)Z
public fun getAvailableForRead ()I
public fun getClosedCause ()Ljava/lang/Throwable;
public fun isClosedForRead ()Z
public fun isClosedForWrite ()Z
public fun read (Laws/smithy/kotlin/runtime/io/SdkBuffer;JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class aws/smithy/kotlin/runtime/auth/awssigning/AwsChunkedSource : aws/smithy/kotlin/runtime/io/SdkSource {
public fun <init> (Laws/smithy/kotlin/runtime/io/SdkSource;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigner;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig;[BLaws/smithy/kotlin/runtime/http/DeferredHeaders;)V
public synthetic fun <init> (Laws/smithy/kotlin/runtime/io/SdkSource;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigner;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig;[BLaws/smithy/kotlin/runtime/http/DeferredHeaders;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun close ()V
public fun read (Laws/smithy/kotlin/runtime/io/SdkBuffer;J)J
}

public final class aws/smithy/kotlin/runtime/auth/awssigning/AwsSignatureType : java/lang/Enum {
public static final field HTTP_REQUEST_CHUNK Laws/smithy/kotlin/runtime/auth/awssigning/AwsSignatureType;
public static final field HTTP_REQUEST_EVENT Laws/smithy/kotlin/runtime/auth/awssigning/AwsSignatureType;
Expand Down Expand Up @@ -103,6 +121,19 @@ public final class aws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig$Co
public final fun invoke (Lkotlin/jvm/functions/Function1;)Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig;
}

public final class aws/smithy/kotlin/runtime/auth/awssigning/AwsSigningResult {
public fun <init> (Ljava/lang/Object;[B)V
public final fun component1 ()Ljava/lang/Object;
public final fun component2 ()[B
public final fun copy (Ljava/lang/Object;[B)Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningResult;
public static synthetic fun copy$default (Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningResult;Ljava/lang/Object;[BILjava/lang/Object;)Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningResult;
public fun equals (Ljava/lang/Object;)Z
public final fun getOutput ()Ljava/lang/Object;
public final fun getSignature ()[B
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public abstract class aws/smithy/kotlin/runtime/auth/awssigning/HashSpecification {
}

Expand Down Expand Up @@ -151,10 +182,20 @@ public final class aws/smithy/kotlin/runtime/auth/awssigning/HashSpecification$U
}

public final class aws/smithy/kotlin/runtime/auth/awssigning/PresignerKt {
public static final fun presignRequest (Laws/smithy/kotlin/runtime/http/request/HttpRequestBuilder;Laws/smithy/kotlin/runtime/operation/ExecutionContext;Laws/smithy/kotlin/runtime/auth/awscredentials/CredentialsProvider;Laws/smithy/kotlin/runtime/http/operation/EndpointResolver;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigner;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class aws/smithy/kotlin/runtime/auth/awssigning/UnsupportedSigningAlgorithmException : aws/smithy/kotlin/runtime/ClientException {
public fun <init> (Ljava/lang/String;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningAlgorithm;)V
public final fun getSigningAlgorithm ()Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningAlgorithm;
}

public final class aws/smithy/kotlin/runtime/auth/awssigning/internal/AwsChunkedUtilKt {
public static final field AWS_CHUNKED_THRESHOLD I
public static final field CHUNK_SIZE_BYTES I
public static final fun getUseAwsChunkedEncoding (Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig;)Z
public static final fun isEligibleForAwsChunkedStreaming (Laws/smithy/kotlin/runtime/http/HttpBody;)Z
public static final fun setAwsChunkedBody (Laws/smithy/kotlin/runtime/http/request/HttpRequestBuilder;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigner;Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig;[BLaws/smithy/kotlin/runtime/http/DeferredHeaders;)V
public static final fun setAwsChunkedHeaders (Laws/smithy/kotlin/runtime/http/request/HttpRequestBuilder;)V
}

41 changes: 41 additions & 0 deletions runtime/auth/http-auth-aws/api/http-auth-aws.api
Original file line number Diff line number Diff line change
@@ -1,4 +1,41 @@
public final class aws/smithy/kotlin/runtime/http/auth/AwsHttpSigner : aws/smithy/kotlin/runtime/http/auth/HttpSigner {
public static final field Companion Laws/smithy/kotlin/runtime/http/auth/AwsHttpSigner$Companion;
public fun <init> (Laws/smithy/kotlin/runtime/http/auth/AwsHttpSigner$Config;)V
public fun sign (Laws/smithy/kotlin/runtime/http/auth/SignHttpRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class aws/smithy/kotlin/runtime/http/auth/AwsHttpSigner$Companion {
public final fun invoke (Lkotlin/jvm/functions/Function1;)Laws/smithy/kotlin/runtime/http/auth/AwsHttpSigner;
}

public final class aws/smithy/kotlin/runtime/http/auth/AwsHttpSigner$Config {
public fun <init> ()V
public final fun getAlgorithm ()Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningAlgorithm;
public final fun getExpiresAfter-FghU774 ()Lkotlin/time/Duration;
public final fun getNormalizeUriPath ()Z
public final fun getOmitSessionToken ()Z
public final fun getService ()Ljava/lang/String;
public final fun getShouldSignHeader ()Lkotlin/jvm/functions/Function1;
public final fun getSignatureType ()Laws/smithy/kotlin/runtime/auth/awssigning/AwsSignatureType;
public final fun getSignedBodyHeader ()Laws/smithy/kotlin/runtime/auth/awssigning/AwsSignedBodyHeader;
public final fun getSigner ()Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigner;
public final fun getUseDoubleUriEncode ()Z
public final fun isUnsignedPayload ()Z
public final fun setAlgorithm (Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningAlgorithm;)V
public final fun setExpiresAfter-BwNAW2A (Lkotlin/time/Duration;)V
public final fun setNormalizeUriPath (Z)V
public final fun setOmitSessionToken (Z)V
public final fun setService (Ljava/lang/String;)V
public final fun setShouldSignHeader (Lkotlin/jvm/functions/Function1;)V
public final fun setSignatureType (Laws/smithy/kotlin/runtime/auth/awssigning/AwsSignatureType;)V
public final fun setSignedBodyHeader (Laws/smithy/kotlin/runtime/auth/awssigning/AwsSignedBodyHeader;)V
public final fun setSigner (Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigner;)V
public final fun setUnsignedPayload (Z)V
public final fun setUseDoubleUriEncode (Z)V
}

public final class aws/smithy/kotlin/runtime/http/auth/EndpointAuthKt {
public static final fun mergeAuthOptions (Ljava/util/List;Ljava/util/List;)Ljava/util/List;
}

public final class aws/smithy/kotlin/runtime/http/auth/SigV4AsymmetricAuthScheme : aws/smithy/kotlin/runtime/http/auth/AuthScheme {
Expand All @@ -12,6 +49,8 @@ public final class aws/smithy/kotlin/runtime/http/auth/SigV4AsymmetricAuthScheme
}

public final class aws/smithy/kotlin/runtime/http/auth/SigV4AsymmetricAuthSchemeKt {
public static final fun sigV4A (ZLjava/lang/String;Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;)Laws/smithy/kotlin/runtime/auth/AuthOption;
public static synthetic fun sigV4A$default (ZLjava/lang/String;Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;ILjava/lang/Object;)Laws/smithy/kotlin/runtime/auth/AuthOption;
}

public final class aws/smithy/kotlin/runtime/http/auth/SigV4AuthScheme : aws/smithy/kotlin/runtime/http/auth/AuthScheme {
Expand All @@ -25,5 +64,7 @@ public final class aws/smithy/kotlin/runtime/http/auth/SigV4AuthScheme : aws/smi
}

public final class aws/smithy/kotlin/runtime/http/auth/SigV4AuthSchemeKt {
public static final fun sigV4 (ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;)Laws/smithy/kotlin/runtime/auth/AuthOption;
public static synthetic fun sigV4$default (ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;ILjava/lang/Object;)Laws/smithy/kotlin/runtime/auth/AuthOption;
}

9 changes: 9 additions & 0 deletions runtime/auth/identity-api/api/identity-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,20 @@ public final class aws/smithy/kotlin/runtime/identity/IdentityProvider$DefaultIm
public static synthetic fun resolve$default (Laws/smithy/kotlin/runtime/identity/IdentityProvider;Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
}

public abstract class aws/smithy/kotlin/runtime/identity/IdentityProviderChain : aws/smithy/kotlin/runtime/identity/CloseableIdentityProvider {
public fun <init> ([Laws/smithy/kotlin/runtime/identity/IdentityProvider;)V
public fun close ()V
protected final fun getProviders ()[Laws/smithy/kotlin/runtime/identity/IdentityProvider;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public abstract interface class aws/smithy/kotlin/runtime/identity/IdentityProviderConfig {
public abstract fun identityProviderForScheme-kHcdgsI (Ljava/lang/String;)Laws/smithy/kotlin/runtime/identity/IdentityProvider;
}

public final class aws/smithy/kotlin/runtime/identity/IdentityProviderConfigKt {
public static final fun asIdentityProviderConfig (Laws/smithy/kotlin/runtime/identity/IdentityProvider;)Laws/smithy/kotlin/runtime/identity/IdentityProviderConfig;
}

public final class aws/smithy/kotlin/runtime/identity/IdentityProviderException : aws/smithy/kotlin/runtime/ClientException {
Expand Down
28 changes: 28 additions & 0 deletions runtime/crt-util/api/crt-util.api
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
public final class aws/smithy/kotlin/runtime/crt/HttpKt {
public static final fun path (Laws/sdk/kotlin/crt/http/HttpRequest;)Ljava/lang/String;
public static final fun queryParameters (Laws/sdk/kotlin/crt/http/HttpRequest;)Laws/smithy/kotlin/runtime/net/url/QueryParameters;
public static final fun toCrtHeaders (Laws/smithy/kotlin/runtime/http/Headers;)Laws/sdk/kotlin/crt/http/Headers;
public static final fun toSdkHeaders (Laws/sdk/kotlin/crt/http/Headers;)Laws/smithy/kotlin/runtime/http/Headers;
public static final fun toSignableCrtRequest (Laws/smithy/kotlin/runtime/http/request/HttpRequest;ZZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun toSignableCrtRequest$default (Laws/smithy/kotlin/runtime/http/request/HttpRequest;ZZLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static final fun update (Laws/smithy/kotlin/runtime/http/request/HttpRequestBuilder;Laws/sdk/kotlin/crt/http/HttpRequest;)V
}

public final class aws/smithy/kotlin/runtime/crt/ReadChannelBodyStream : aws/sdk/kotlin/crt/http/HttpRequestBodyStream, kotlinx/coroutines/CoroutineScope {
public fun <init> (Laws/smithy/kotlin/runtime/io/SdkByteReadChannel;Lkotlin/coroutines/CoroutineContext;)V
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
public fun resetPosition ()Z
public fun sendRequestBody (Laws/sdk/kotlin/crt/io/MutableBuffer;)Z
}

public final class aws/smithy/kotlin/runtime/crt/SdkDefaultIO {
public static final field INSTANCE Laws/smithy/kotlin/runtime/crt/SdkDefaultIO;
public final fun getClientBootstrap ()Laws/sdk/kotlin/crt/io/ClientBootstrap;
public final fun getEventLoop ()Laws/sdk/kotlin/crt/io/EventLoopGroup;
public final fun getHostResolver ()Laws/sdk/kotlin/crt/io/HostResolver;
public final fun getTlsContext ()Laws/sdk/kotlin/crt/io/TlsContext;
}

public final class aws/smithy/kotlin/runtime/crt/SdkSourceBodyStream : aws/sdk/kotlin/crt/http/HttpRequestBodyStream {
public fun <init> (Laws/smithy/kotlin/runtime/io/SdkSource;)V
public fun resetPosition ()Z
public fun sendRequestBody (Laws/sdk/kotlin/crt/io/MutableBuffer;)Z
}

Loading
Loading