diff --git a/.github/workflows/sem_ver.yml b/.github/workflows/sem_ver.yml
new file mode 100644
index 000000000..8f0142c54
--- /dev/null
+++ b/.github/workflows/sem_ver.yml
@@ -0,0 +1,53 @@
+# This workflow tests the installation of semantic release
+name: Semantic Release Test Installation
+
+on:
+ pull_request:
+
+jobs:
+ semantic-release:
+ runs-on: macos-latest
+ permissions:
+ id-token: write
+ contents: read
+ steps:
+ - name: Support longpaths on Git checkout
+ run: |
+ git config --global core.longpaths true
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ # We need access to the role that is able to get CI Bot Creds
+ - name: Configure AWS Credentials for Release
+ uses: aws-actions/configure-aws-credentials@v2
+ with:
+ aws-region: us-west-2
+ role-to-assume: arn:aws:iam::587316601012:role/GitHub-CI-CI-Bot-Credential-Access-Role-us-west-2
+ role-session-name: CI_Bot_Release
+
+ - name: Upgrade Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 21
+
+ # Use AWS Secrets Manger GHA to retrieve CI Bot Creds
+ - name: Get CI Bot Creds Secret
+ uses: aws-actions/aws-secretsmanager-get-secrets@v2
+ with:
+ secret-ids: Github/aws-crypto-tools-ci-bot
+ parse-json-secrets: true
+
+ # Log in as the CI Bot
+ - name: Log in as CI Bot
+ run: |
+ echo ${{env.GITHUB_AWS_CRYPTO_TOOLS_CI_BOT_ESDK_RELEASE_TOKEN}} > token.txt
+ gh auth login --with-token < token.txt
+ rm token.txt
+ gh auth status
+
+ # Test to see if we can setup semantic release
+ - name: Test Semantic Release Installation
+ uses: actions/checkout@v4
+ - run: |
+ make setup_semantic_release
diff --git a/.github/workflows/semantic_release.yml b/.github/workflows/semantic_release.yml
new file mode 100644
index 000000000..5e9a9bcec
--- /dev/null
+++ b/.github/workflows/semantic_release.yml
@@ -0,0 +1,77 @@
+# This workflow runs semantic release, bumps, generates changelog, and tags the project
+name: Semantic Release
+
+on:
+ workflow_dispatch:
+ inputs:
+ dry-run:
+ description: "Is this a dry run to validate semantic-release behaves as expected? (y/n)"
+ required: true
+ type: string
+
+jobs:
+ semantic-release:
+ # there is no easy way in gha to check if the actor is part of the team, running semantic release is a more
+ # privileged operation, so we must make sure this list of users is a subset of the users labeled as maintainers of
+ # https://github.com/orgs/aws/teams/aws-crypto-tools
+ if: contains('["seebees","texastony","ShubhamChaturvedi7","lucasmcdonald3","josecorella","imabhichow","rishav-karanjit","antonf-amzn","justplaz","ajewellamz","RitvikKapila"]', github.actor)
+ runs-on: macos-latest
+ permissions:
+ id-token: write
+ contents: write
+ steps:
+ - name: Support longpaths on Git checkout
+ run: |
+ git config --global core.longpaths true
+ - uses: actions/checkout@v3
+ # We only pull in the submodules we need to build the library
+ - run: git submodule update --init libraries
+
+ # We need access to the role that is able to get CI Bot Creds
+ - name: Configure AWS Credentials for Release
+ uses: aws-actions/configure-aws-credentials@v2
+ with:
+ aws-region: us-west-2
+ role-to-assume: arn:aws:iam::587316601012:role/GitHub-CI-CI-Bot-Credential-Access-Role-us-west-2
+ role-session-name: CI_Bot_Release
+
+ - name: Upgrade Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 21
+
+ # Use AWS Secrets Manger GHA to retrieve CI Bot Creds
+ - name: Get CI Bot Creds Secret
+ uses: aws-actions/aws-secretsmanager-get-secrets@v2
+ with:
+ secret-ids: Github/aws-crypto-tools-ci-bot
+ parse-json-secrets: true
+
+ # Log in as the CI Bot
+ - name: Log in as CI Bot
+ run: |
+ echo ${{env.GITHUB_AWS_CRYPTO_TOOLS_CI_BOT_ESDK_RELEASE_TOKEN}} > token.txt
+ gh auth login --with-token < token.txt
+ rm token.txt
+ gh auth status
+
+ # Set up semantic release
+ - name: Setup Semantic Release
+ run: |
+ make setup_semantic_release
+
+ # Run semantic release in dry run mode if input matches
+ - name: Run Semantic Release in dry run mode
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ if: ${{inputs.dry-run == 'y'}}
+ run: |
+ make dry_run_semantic_release
+
+ # Run semantic release if input matches
+ - name: Run Semantic Release
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ if: ${{inputs.dry-run == 'n'}}
+ run: |
+ make run_semantic_release
diff --git a/.releaserc.cjs b/.releaserc.cjs
new file mode 100644
index 000000000..1c44fd796
--- /dev/null
+++ b/.releaserc.cjs
@@ -0,0 +1,160 @@
+// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+/*
+ First run `make setup_semantic_release` to install the required dependencies.
+
+ Using this config semantic-release will search for the latest tag
+ evaluate all commits after that tag
+ generate release notes and a version bump.
+ It will commit these changes, push these changes, and publish a new version tag.
+
+ This file requires a `--branches` option to function.
+ This is to facilitate point releases if needed.
+
+ `npx semantic-release --branches main`
+*/
+
+// This project has several runtimes
+// each one has files that need to be updated.
+// We model all the files and the runtimes here in this structure
+const Runtimes = {
+ java: {
+ "project.properties": {
+ dependencies: [],
+ },
+ },
+ net: {
+ "DynamoDbEncryption/runtimes/net/DynamoDbEncryption.csproj": {
+ dependencies: [],
+ assemblyInfo: "DynamoDbEncryption/runtimes/net/AssemblyInfo.cs",
+ }
+ },
+};
+
+/**
+ * @type {import('semantic-release').GlobalConfig}
+ */
+module.exports = {
+ branches: ["main"],
+ repositoryUrl:
+ "git@github.com:aws/aws-database-encryption-sdk-dynamodb.git",
+ plugins: [
+ // Check the commits since the last release
+ ["@semantic-release/commit-analyzer",
+ {
+ "preset": "conventionalcommits",
+ "parserOpts": {
+ "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"]
+ },
+ "presetConfig": {
+ "types": [
+ {"type": "feat", "section": "Features"},
+ {"type": "fix", "section": "Fixes"},
+ {"type": "chore", "section": "Maintenance"},
+ {"type": "docs", "section": "Maintenance"},
+ {"type": "revert", "section": "Fixes"},
+ {"type": "style", "hidden": true},
+ {"type": "refactor", "hidden": true},
+ {"type": "perf", "hidden": true},
+ {"type": "test", "hidden": true}
+ ]
+ },
+ "releaseRules": [
+ {"type": "docs", "release": "patch"},
+ {"type": "revert", "release": "patch"},
+ {"type": "chore", "release": "patch"}
+ ]
+ },
+ ],
+ // Based on the commits generate release notes
+ ["@semantic-release/release-notes-generator",
+ {
+ "preset": "conventionalcommits",
+ "parserOpts": {
+ "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"]
+ },
+ "presetConfig": {
+ "types": [
+ {"type": "feat", "section": "Features"},
+ {"type": "fix", "section": "Fixes"},
+ {"type": "chore", "section": "Maintenance"},
+ {"type": "docs", "section": "Maintenance"},
+ {"type": "revert", "section": "Fixes"},
+ {"type": "style", "hidden": true},
+ {"type": "refactor", "hidden": true},
+ {"type": "perf", "hidden": true},
+ {"type": "test", "hidden": true}
+ ]
+ }
+ }
+ ],
+ // Update the change log with the generated release notes
+ [
+ "@semantic-release/changelog",
+ {
+ changelogFile: "CHANGELOG.md",
+ changelogTitle: "# Changelog",
+ },
+ ],
+
+ // Bump the various versions
+ [
+ "semantic-release-replace-plugin",
+ {
+ replacements: [
+ // Update the version for all Gradle Java projects
+ // Does not update the dependencies
+ {
+ files: Object.keys(Runtimes.java),
+ from: "projectJavaVersion=.*",
+ to: 'projectJavaVersion=${nextRelease.version}',
+ results: Object.keys(Runtimes.java).map(CheckResults),
+ countMatches: true,
+ },
+ // Update the version for all DotNet projects
+ // Does not update the dependencies
+ {
+ files: Object.keys(Runtimes.net),
+ from: ".*",
+ to: "${nextRelease.version}",
+ results: Object.keys(Runtimes.net).map(CheckResults),
+ countMatches: true,
+ },
+ // Update the AssmeblyInfo.cs file of the DotNet projects
+ ...Object.entries(Runtimes.net).flatMap(
+ ([file, { assemblyInfo }]) => ({
+ files: assemblyInfo,
+ from: "assembly: AssemblyVersion(.*)",
+ to: 'assembly: AssemblyVersion("${nextRelease.version}")]',
+ results: [CheckResults(assemblyInfo)],
+ countMatches: true,
+ }),
+ ),
+ ],
+ },
+ ],
+ // Commit and push changes the changelog and versions bumps
+ [
+ "@semantic-release/git",
+ {
+ assets: [
+ "CHANGELOG.md",
+ ...Object.values(Runtimes).flatMap((r) => Object.keys(r)),
+ ...Object.values(Runtimes.net).flatMap((r) => r.assemblyInfo),
+ ],
+ message:
+ "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}",
+ },
+ ],
+ ],
+};
+
+function CheckResults(file) {
+ return {
+ file,
+ hasChanged: true,
+ numMatches: 1,
+ numReplacements: 1,
+ };
+}
diff --git a/Makefile b/Makefile
index 9b0efd9da..c95099be4 100644
--- a/Makefile
+++ b/Makefile
@@ -51,3 +51,12 @@ generate_properties_file:
--namespace aws.polymorph \
--properties-file $(PROJECT_ROOT)/smithy-dafny-project.properties \
";
+
+setup_semantic_release:
+ npm i --no-save semantic-release @semantic-release/changelog semantic-release-replace-plugin conventional-changelog-conventionalcommits @semantic-release/git
+
+run_semantic_release:
+ npx semantic-release --no-ci
+
+dry_run_semantic_release:
+ npx semantic-release --dry-run