Unverified Commit a5e2c4bb authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

Support `version` when generating an SDK (#424)

* Support `version` when generating an SDK

This adds support for specifying `version` in `runtimeConfig` which will modify dependencies to the Runtime crates to use the specified version instead of a path dependency.

* CR feedback & fix AWS tests

* Cleanup code to catch hard crash
parent 43936cbb
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -8,15 +8,19 @@ package software.amazon.smithy.rustsdk
import software.amazon.smithy.rust.codegen.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.rustlang.Local
import software.amazon.smithy.rust.codegen.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.smithy.RuntimeCrateLocation
import java.io.File
import java.nio.file.Path

fun RuntimeConfig.awsRoot(): String {
    val asPath = Path.of(relativePath)

    check(runtimeCrateLocation is RuntimeCrateLocation.Path) { "cannot run tests on versioned runtime dependencies" }
    val cratePath = (runtimeCrateLocation as RuntimeCrateLocation.Path).path
    val asPath = Path.of(cratePath)
    val path = if (asPath.isAbsolute) {
        asPath.parent.resolve("aws/rust-runtime").toAbsolutePath().toString()
    } else {
        relativePath
        cratePath
    }
    check(File(path).exists()) { "$path must exist to generate a working SDK" }
    return path
+3 −2
Original line number Diff line number Diff line
@@ -5,15 +5,16 @@

package software.amazon.smithy.rustsdk

import software.amazon.smithy.rust.codegen.smithy.RuntimeCrateLocation
import software.amazon.smithy.rust.codegen.testutil.TestRuntimeConfig
import java.io.File

// In aws-sdk-codegen, the working dir when gradle runs tests is actually `./aws`. So, to find the smithy runtime, we need
// to go up one more level
val AwsTestRuntimeConfig = TestRuntimeConfig.copy(
    relativePath = run {
    runtimeCrateLocation = run {
        val path = File("../../rust-runtime")
        check(path.exists()) { "$path must exist to generate a working SDK" }
        path.absolutePath
        RuntimeCrateLocation.Path(path.absolutePath)
    }
)
+7 −10
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import software.amazon.smithy.codegen.core.SymbolDependency
import software.amazon.smithy.codegen.core.SymbolDependencyContainer
import software.amazon.smithy.rust.codegen.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.smithy.crateLocation
import software.amazon.smithy.rust.codegen.util.dq

sealed class DependencyScope {
@@ -104,6 +105,7 @@ class InlineDependency(

        fun wrappedXmlErrors(runtimeConfig: RuntimeConfig): InlineDependency =
            forRustFile("rest_xml_wrapped_errors", CargoDependency.smithyXml(runtimeConfig))

        fun unwrappedXmlErrors(runtimeConfig: RuntimeConfig): InlineDependency =
            forRustFile("rest_xml_unwrapped_errors", CargoDependency.smithyXml(runtimeConfig))
    }
@@ -176,21 +178,16 @@ data class CargoDependency(
    companion object {
        val FastRand = CargoDependency("fastrand", CratesIo("1"))
        val Http: CargoDependency = CargoDependency("http", CratesIo("0.2"))
        fun SmithyTypes(runtimeConfig: RuntimeConfig) =
            CargoDependency("${runtimeConfig.cratePrefix}-types", Local(runtimeConfig.relativePath))
        fun SmithyTypes(runtimeConfig: RuntimeConfig) = runtimeConfig.runtimeCrate("types")

        fun SmithyHttp(runtimeConfig: RuntimeConfig) = CargoDependency(
            "${runtimeConfig.cratePrefix}-http", Local(runtimeConfig.relativePath)
        )
        fun SmithyHttp(runtimeConfig: RuntimeConfig) = runtimeConfig.runtimeCrate("http")

        fun ProtocolTestHelpers(runtimeConfig: RuntimeConfig) = CargoDependency(
            "protocol-test-helpers", Local(runtimeConfig.relativePath), scope = DependencyScope.Dev
            "protocol-test-helpers", runtimeConfig.runtimeCrateLocation.crateLocation(), scope = DependencyScope.Dev
        )

        fun smithyJson(runtimeConfig: RuntimeConfig): CargoDependency =
            CargoDependency("${runtimeConfig.cratePrefix}-json", Local(runtimeConfig.relativePath))
        fun smithyXml(runtimeConfig: RuntimeConfig): CargoDependency =
            CargoDependency("${runtimeConfig.cratePrefix}-xml", Local(runtimeConfig.relativePath))
        fun smithyJson(runtimeConfig: RuntimeConfig): CargoDependency = runtimeConfig.runtimeCrate("json")
        fun smithyXml(runtimeConfig: RuntimeConfig): CargoDependency = runtimeConfig.runtimeCrate("xml")

        val SerdeJson: CargoDependency =
            CargoDependency("serde_json", CratesIo("1"), features = listOf("float_roundtrip"))
+3 −2
Original line number Diff line number Diff line
@@ -91,9 +91,10 @@ class CodegenVisitor(context: PluginContext, private val codegenDecorator: RustC
        )
        try {
            "cargo fmt".runCommand(fileManifest.baseDir, timeout = 10)
        } catch (_: CommandFailed) {
            logger.warning("Generated output did not parse [${service.id}]")
        } catch (err: CommandFailed) {
            logger.warning("Failed to run cargo fmt: [${service.id}]\n${err.output}")
        }

        logger.info("Rust Client generation complete!")
    }

+31 −4
Original line number Diff line number Diff line
@@ -9,27 +9,51 @@ import software.amazon.smithy.codegen.core.Symbol
import software.amazon.smithy.model.node.ObjectNode
import software.amazon.smithy.model.traits.TimestampFormatTrait
import software.amazon.smithy.rust.codegen.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.rustlang.CratesIo
import software.amazon.smithy.rust.codegen.rustlang.DependencyLocation
import software.amazon.smithy.rust.codegen.rustlang.InlineDependency
import software.amazon.smithy.rust.codegen.rustlang.Local
import software.amazon.smithy.rust.codegen.rustlang.RustDependency
import software.amazon.smithy.rust.codegen.rustlang.RustType
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.asType
import java.util.Optional

data class RuntimeConfig(val cratePrefix: String = "smithy", val relativePath: String = "../") {
sealed class RuntimeCrateLocation {
    data class Path(val path: String) : RuntimeCrateLocation()
    data class Versioned(val version: String) : RuntimeCrateLocation()
}

fun RuntimeCrateLocation.crateLocation(): DependencyLocation = when (this) {
    is RuntimeCrateLocation.Path -> Local(this.path)
    is RuntimeCrateLocation.Versioned -> CratesIo(this.version)
}

data class RuntimeConfig(
    val cratePrefix: String = "smithy",
    val runtimeCrateLocation: RuntimeCrateLocation = RuntimeCrateLocation.Path("../")
) {
    companion object {

        fun fromNode(node: Optional<ObjectNode>): RuntimeConfig {
            return if (node.isPresent) {
                val runtimeCrateLocation = if (node.get().containsMember("version")) {
                    RuntimeCrateLocation.Versioned(node.get().expectStringMember("version").value)
                } else {
                    RuntimeCrateLocation.Path(node.get().getStringMemberOrDefault("relativePath", "../"))
                }
                RuntimeConfig(
                    node.get().getStringMemberOrDefault("cratePrefix", "smithy"),
                    node.get().getStringMemberOrDefault("relativePath", "../")
                    runtimeCrateLocation = runtimeCrateLocation
                )
            } else {
                RuntimeConfig()
            }
        }
    }

    fun runtimeCrate(runtimeCrateName: String): CargoDependency =
        CargoDependency("$cratePrefix-$runtimeCrateName", runtimeCrateLocation.crateLocation())
}

data class RuntimeType(val name: String?, val dependency: RustDependency?, val namespace: String) {
@@ -201,7 +225,10 @@ data class RuntimeType(val name: String?, val dependency: RustDependency?, val n
            namespace = "smithy_http::response"
        )

        fun wrappedXmlErrors(runtimeConfig: RuntimeConfig) = forInlineDependency(InlineDependency.wrappedXmlErrors(runtimeConfig))
        fun unwrappedXmlErrors(runtimeConfig: RuntimeConfig) = forInlineDependency(InlineDependency.unwrappedXmlErrors(runtimeConfig))
        fun wrappedXmlErrors(runtimeConfig: RuntimeConfig) =
            forInlineDependency(InlineDependency.wrappedXmlErrors(runtimeConfig))

        fun unwrappedXmlErrors(runtimeConfig: RuntimeConfig) =
            forInlineDependency(InlineDependency.unwrappedXmlErrors(runtimeConfig))
    }
}
Loading