Skip to content
Merged
114 changes: 114 additions & 0 deletions .github/workflows/go-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: Go Release Automation

on:
workflow_dispatch:
inputs:
project-name:
description: "Project name (e.g., DynamoDbEncryption)"
required: true
type: string
version:
description: "Version (e.g., v0.1.0)"
required: true
type: string

jobs:
get-dafny-version:
uses: ./.github/workflows/dafny_version.yml

go-release:
needs: get-dafny-version
runs-on: macos-13
permissions:
contents: write
pull-requests: write
id-token: write

steps:
- name: Support longpaths on Git checkout
run: |
git config --global core.longpaths true

# KMS and MPL tests need to use credentials which can call KMS
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-west-2
role-to-assume: arn:aws:iam::370957321024:role/GitHub-CI-DDBEC-Dafny-Role-us-west-2
role-session-name: GoRelease-DBESDK-Tests

- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Update submodules
run: |
git submodule update --init --recursive

- name: Setup Dafny
uses: dafny-lang/setup-dafny-action@v1.8.0
with:
dafny-version: ${{ needs.get-dafny-version.outputs.version }}

- name: Install Go
uses: actions/setup-go@v5
with:
go-version: "1.23"

- name: Install Go imports
run: |
go install golang.org/x/tools/cmd/goimports@latest

- name: Install Smithy-Dafny codegen dependencies
uses: ./.github/actions/install_smithy_dafny_codegen_dependencies

- name: Configure Git
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"

- name: Get release directory name
id: release-dir
run: |
chmod +x ./scripts/go-release-automation.sh
RELEASE_DIR_NAME=$(./scripts/go-release-automation.sh get_release_dir_name "${{ github.event.inputs.project-name }}" "${{ github.event.inputs.version }}")
echo "releaseDirName=$RELEASE_DIR_NAME" >> $GITHUB_OUTPUT

- name: Generate a changelog
uses: orhun/git-cliff-action@v4
with:
config: releases/go/.git-cliff.toml
args: --bump -u --prepend releases/go/${{ steps.release-dir.outputs.releaseDirName }}/CHANGELOG.md

- name: Run Go release automation script
run: |
chmod +x ./scripts/go-release-automation.sh
./scripts/go-release-automation.sh run_release_script ${{ github.event.inputs.project-name }} ${{ github.event.inputs.version }}

- name: Create Pull Request
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PROJECT_NAME="${{ github.event.inputs.project-name }}"
VERSION="${{ github.event.inputs.version }}"

# Get the release directory name using the sourced function
RELEASE_DIR_NAME="${{ steps.release-dir.outputs.releaseDirName }}"

BRANCH_NAME="golang-release-staging-branch/$RELEASE_DIR_NAME/$VERSION"

DIFF_FILES=$(diff -qr $PROJECT_NAME/runtimes/go/ImplementationFromDafny-go releases/go/$RELEASE_DIR_NAME || true)

# Create PR using GitHub CLI
gh pr create \
--title "chore(go): Release $RELEASE_DIR_NAME Go module $VERSION" \
--body "This PR was automatically created by the Go Release Automation workflow. It releases version $VERSION of the $RELEASE_DIR_NAME Go module. The diff between $PROJECT_NAME/runtimes/go/ImplementationFromDafny-go and releases/go/$RELEASE_DIR_NAME is below:

$DIFF_FILES
" \
--base main \
--head "$BRANCH_NAME" \
--label "golang" \
--draft
21 changes: 21 additions & 0 deletions releases/go/.git-cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[git]
tag_pattern = "^releases/go/mpl/v*"
filter_commits = true
commit_parsers = [
{ message = '^feat\((go|all languages)\)', group = "Features"},
{ message = '^fix\((go|all languages)\)', group = "Fixes"},
{ message = '^chore\((go|all languages)\)', group = "Maintenance"},
{ message = '^docs\((go|all languages)\)', group = "Maintenance"},
{ message = '^revert\((go|all languages)\)', group = "Fixes"},
{ message = '^style\((go|all languages)\)', group = "Miscellaneous"},
{ message = '^refactor\((go|all languages)\)', group = "Miscellaneous"},
{ message = '^perf\((go|all languages)\)', group = "Miscellaneous"},
{ message = '^test\((go|all languages)\)', group = "Miscellaneous"},
]
commit_preprocessors = [
{ pattern = '\(dafny\)', replace = '(all languages)'}
]

[changelog]
header = "# Changelog\n\n"
trim = true
107 changes: 107 additions & 0 deletions scripts/go-release-automation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/bash

# Go Release Process Script
# Used for copying go files to release directory and make a commit

set -e # Exit on error

# Check if project name and version is provided
if [ $# -ne 3 ]; then
echo "Usage: $0 <function> <project-name> [version]"
echo "Example: $0 get_release_dir_name DynamoDbEncryption v0.1.0"
echo "Example: $0 run_release_script DynamoDbEncryption v0.1.0"
exit 1
fi

# Function to map project name to release directory name
get_release_dir_name() {
local project=$1
case "$project" in
"DynamoDbEncryption") echo "dynamodb-esdk" ;;
*) echo "Error: Unknown project name: $project" >&2; return 1 ;;
esac
}

run_release_script() {
PROJECT_NAME=$1
VERSION=$2

echo "Starting Go release script for $PROJECT_NAME $VERSION"

# Pull the latest smithy-dafny and libraries git submodules
echo " Pulling latest git submodules..."
git submodule update --init --recursive

# Go to the project directory
echo " Navigating to $PROJECT_NAME..."
cd "$PROJECT_NAME" || { echo "Error: Project directory $PROJECT_NAME not found"; exit 1; }

# Build using make commands
echo " Building project..."
make polymorph_dafny
make polymorph_go
make transpile_go
make test_go

# Run Go tools in ImplementationFromDafny-go
echo " Running Go tools in ImplementationFromDafny-go..."
cd runtimes/go/ImplementationFromDafny-go || { echo "Error: ImplementationFromDafny-go directory not found"; exit 1; }

find . -name "*shim.go" -type f -delete
echo "Removed all shim.go files"

echo "Running goimports..."
goimports -w .

echo "Running go get -u..."
go get -u

echo "Running go mod tidy..."
go mod tidy

echo "Running go build to check for errors..."
go build --gcflags="-e" ./...

# Replacement directives are removed to get package from go pkg instead of local copy
echo "Removing all replace directives from go.mod..."
go mod edit -json | jq -r '.Replace[].Old.Path' | xargs -n1 go mod edit -dropreplace

# Get the mapped release directory name
RELEASE_DIR_NAME=$(get_release_dir_name "$PROJECT_NAME")

# Copy files to releases directory
echo " Copying files to releases/go/$RELEASE_DIR_NAME..."

# Use rsync to copy files while excluding following ones:
# ImplementationFromDafny.go: This file is for devlopment. Users is expected use API(s) from `*/api_client.go`
# ImplementationFromDafny-go.dtr: This is the dafny translation record only needed for code generation
# go.sum: This files will be updated by go mod tidy
rsync -av --exclude="ImplementationFromDafny.go" --exclude="ImplementationFromDafny-go.dtr" --exclude="go.sum" ./ "$(git rev-parse --show-toplevel)/releases/go/$RELEASE_DIR_NAME/"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Note: unlike MPL, I am copying go.mod file as well. The reason is because go.mod does not exists (because we have never released DB-ESDK Go). So, all the go related commands (example: goimports, go get, go mod tidy...) won't work. I am also inclining towards making this change in MPL.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't understand this, but I trust you


# Run Go tools in releases directory
echo "Running Go tools in releases/go/$RELEASE_DIR_NAME..."

cd "$(git rev-parse --show-toplevel)/releases/go/$RELEASE_DIR_NAME/" || { echo "Error: releases directory not found"; exit 1; }

echo "Running goimports..."
goimports -w .
echo "Running go get -u..."
go get -u ./...

echo "Running go mod tidy..."
go mod tidy

echo "Running go build to check for errors..."
go build --gcflags="-e" ./...

# Prepare for commit
echo "creating a branch..."

git checkout -b "golang-release-staging-branch/$RELEASE_DIR_NAME/${VERSION}"
git add *

git commit -m "Release $RELEASE_DIR_NAME Go module ${VERSION}"
git push origin "golang-release-staging-branch/$RELEASE_DIR_NAME/${VERSION}"
}

"$@"
Loading