Skip to content

Commit

Permalink
Add codegen version to generated package (#1621)
Browse files Browse the repository at this point in the history
* Add codegen version to generated package metadata

* Update `CHANGELOG.next.toml`

* Remove unnecessary try-catch block from `smithyCodegenVersion`

* Add git commit hash to version

* Fix version filename

* Add tests for `Version`

* Store version in "$smithyRsVersion\n$gitCommitHash" format

* Make version parsing more strict
  • Loading branch information
unexge authored Aug 12, 2022
1 parent 48a8531 commit 610d963
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 6 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@
# message = "Fix typos in module documentation for generated crates"
# references = ["smithy-rs#920"]
# meta = { "breaking" = false, "tada" = false, "bug" = false, "sdk" = "client | server | all"}
# author = "rcoh"
# author = "rcoh"

[[smithy-rs]]
message = "Add codegen version to generated package metadata"
references = ["smithy-rs#1612"]
meta = { "breaking" = false, "tada" = false, "bug" = false }
author = "unexge"
17 changes: 16 additions & 1 deletion codegen/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import java.io.ByteArrayOutputStream

plugins {
kotlin("jvm")
Expand Down Expand Up @@ -39,6 +40,18 @@ tasks.compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}

fun gitCommitHash() =
try {
val output = ByteArrayOutputStream()
exec {
commandLine = listOf("git", "rev-parse", "HEAD")
standardOutput = output
}
output.toString().trim()
} catch (ex: Exception) {
"unknown"
}

val generateSmithyRuntimeCrateVersion by tasks.registering {
// generate the version of the runtime to use as a resource.
// this keeps us from having to manually change version numbers in multiple places
Expand All @@ -47,9 +60,11 @@ val generateSmithyRuntimeCrateVersion by tasks.registering {
outputs.file(versionFile)
val crateVersion = project.properties["smithy.rs.runtime.crate.version"].toString()
inputs.property("crateVersion", crateVersion)
// version format must be in sync with `software.amazon.smithy.rust.codegen.smithy.Version`
val version = "$crateVersion\n${gitCommitHash()}"
sourceSets.main.get().output.dir(resourcesDir)
doLast {
versionFile.writeText(crateVersion)
versionFile.writeText(version)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ fun RuntimeCrateLocation.crateLocation(): DependencyLocation = when (this.path)
}

fun defaultRuntimeCrateVersion(): String {
// generated as part of the build, see codegen/build.gradle.kts
try {
return object {}.javaClass.getResource("runtime-crate-version.txt")?.readText()
?: throw CodegenException("sdk-version.txt does not exist")
return Version.crateVersion()
} catch (ex: Exception) {
throw CodegenException("failed to load sdk-version.txt which sets the default client-runtime version", ex)
throw CodegenException("failed to get crate version which sets the default client-runtime version", ex)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rust.codegen.smithy

import software.amazon.smithy.codegen.core.CodegenException

// generated as part of the build, see codegen/build.gradle.kts
private const val VERSION_FILENAME = "runtime-crate-version.txt"

data class Version(val fullVersion: String, val crateVersion: String) {
companion object {
// Version must be in the "{smithy_rs_version}\n{git_commit_hash}" format
fun parse(content: String): Version {
val lines = content.lines()
if (lines.size != 2) {
throw IllegalArgumentException("Invalid version format, it should contain `2` lines but contains `${lines.size}` line(s)")
}
return Version(lines.joinToString("-"), lines.first())
}

// Returns full version in the "{smithy_rs_version}-{git_commit_hash}" format
fun fullVersion(): String =
fromDefaultResource().fullVersion

fun crateVersion(): String =
fromDefaultResource().crateVersion

private fun fromDefaultResource(): Version =
parse(
object {}.javaClass.getResource(VERSION_FILENAME)?.readText()
?: throw CodegenException("$VERSION_FILENAME does not exist"),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import software.amazon.smithy.rust.codegen.rustlang.DependencyScope
import software.amazon.smithy.rust.codegen.rustlang.Feature
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.smithy.CoreRustSettings
import software.amazon.smithy.rust.codegen.smithy.Version
import software.amazon.smithy.rust.codegen.util.deepMergeWith

/**
Expand Down Expand Up @@ -63,6 +64,11 @@ class CargoTomlGenerator(
"edition" to "2021",
"license" to settings.license,
"repository" to settings.moduleRepository,
"metadata" to listOfNotNull(
"smithy" to listOfNotNull(
"codegen-version" to Version.fullVersion(),
).toMap(),
).toMap(),
).toMap(),
"dependencies" to dependencies.filter { it.scope == DependencyScope.Compile }
.associate { it.name to it.toMap() },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rust.codegen.smithy

import io.kotest.assertions.throwables.shouldThrowAny
import io.kotest.matchers.shouldBe
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource

class VersionTest {
@ParameterizedTest()
@MethodSource("versionProvider")
fun `parses version`(
content: String,
fullVersion: String,
crateVersion: String,
) {
val version = Version.parse(content)
version.fullVersion shouldBe fullVersion
version.crateVersion shouldBe crateVersion
}

@ParameterizedTest()
@MethodSource("invalidVersionProvider")
fun `fails to parse version`(
content: String,
) {
shouldThrowAny { Version.parse(content) }
}

companion object {
@JvmStatic
fun versionProvider() = listOf(
Arguments.of(
"0.47.0\n0198d26096eb1af510ce24766c921ffc5e4c191e",
"0.47.0-0198d26096eb1af510ce24766c921ffc5e4c191e",
"0.47.0",
),
Arguments.of(
"release-2022-08-04\ndb48039065bec890ef387385773b37154b555b14",
"release-2022-08-04-db48039065bec890ef387385773b37154b555b14",
"release-2022-08-04",
),
Arguments.of(
"0.30.0-alpha\na1dbbe2947de3c8bbbef9446eb442e298f83f200",
"0.30.0-alpha-a1dbbe2947de3c8bbbef9446eb442e298f83f200",
"0.30.0-alpha",
),
Arguments.of(
"0.6-rc1.cargo\nc281800a185b34600b05f8b501a0322074184123",
"0.6-rc1.cargo-c281800a185b34600b05f8b501a0322074184123",
"0.6-rc1.cargo",
),
Arguments.of(
"0.27.0-alpha.1\n643f2ee",
"0.27.0-alpha.1-643f2ee",
"0.27.0-alpha.1",
),
)

@JvmStatic
fun invalidVersionProvider() = listOf("0.0.0", "")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rust.codegen.smithy.generators

import org.junit.jupiter.api.Test
import software.amazon.smithy.rust.codegen.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.rustlang.CratesIo
import software.amazon.smithy.rust.codegen.smithy.Version
import software.amazon.smithy.rust.codegen.testutil.TestWorkspace
import software.amazon.smithy.rust.codegen.testutil.compileAndTest
import software.amazon.smithy.rust.codegen.testutil.unitTest

class CargoTomlGeneratorTest {
private val CargoMetadata: CargoDependency = CargoDependency("cargo_metadata", CratesIo("0.15.0"))

@Test
fun `adds codegen version to package metadata`() {
val project = TestWorkspace.testProject()
project.lib { writer ->
writer.addDependency(CargoMetadata)
writer.unitTest(
"smithy_codegen_version_in_package_metadata",
"""
let metadata = cargo_metadata::MetadataCommand::new()
.exec()
.expect("could not run `cargo metadata`");
let pgk_metadata = &metadata.root_package().expect("missing root package").metadata;
let codegen_version = pgk_metadata
.get("smithy")
.and_then(|s| s.get("codegen-version"))
.expect("missing `smithy.codegen-version` field")
.as_str()
.expect("`smithy.codegen-version` is not str");
assert_eq!(codegen_version, "${Version.fullVersion()}");
""",
)
}
project.compileAndTest()
}
}

0 comments on commit 610d963

Please sign in to comment.