diff --git a/.github/actions/create-pr/action.yml b/.github/actions/create-pr/action.yml
new file mode 100644
index 0000000000..470262609e
--- /dev/null
+++ b/.github/actions/create-pr/action.yml
@@ -0,0 +1,92 @@
+name: "Create PR custom action"
+description: "Create a PR and a temporary branch, close duplicates"
+
+# PROCESS
+#
+# 1. Setup git client using Powertools for AWS Lambda bot username
+# 2. Pushes staged files to a temporary branch
+# 3. Creates a PR from temporary branch against a target branch (typically trunk: develop, main, etc.)
+# 4. Searches for duplicate PRs with the same title
+# 5. If duplicates are found, link to the most recent one, close and delete their branches so we keep a single PR
+# 6. In the event of failure, we delete the now orphaned branch (if any), and propagate the failure
+
+# REQUIREMENTS
+# You need to enable "Allow GitHub Actions to create and approve pull requests" in your repository settings
+# You need to have "skip-changelog" label in your repository to skip changelog generation.
+
+# USAGE
+#
+# - name: Create PR
+# id: create-pr
+# uses: ./.github/actions/create-pr
+# with:
+# files: "CHANGELOG.md"
+# temp_branch_prefix: "ci-changelog"
+# pull_request_title: "chore(ci): changelog rebuild"
+# github_token: ${{ secrets.GITHUB_TOKEN }}
+# - name: Step to demonstrate how to access outputs (no need for this)
+# run: |
+# echo "PR number: ${PR_ID}"
+# echo "Branch: ${BRANCH}"
+# env:
+# PR_ID: ${{ steps.create-pr.outputs.pull_request_id}}
+# BRANCH: ${{ steps.create-pr.outputs.temp_branch}}
+
+inputs:
+ files:
+ description: "Files to add separated by space"
+ required: true
+ temp_branch_prefix:
+ description: "Prefix for temporary git branch to be created, e.g, ci-docs"
+ required: true
+ pull_request_title:
+ description: "Pull Request title to use"
+ required: true
+ github_token:
+ description: "GitHub token for GitHub CLI"
+ required: true
+ target_branch:
+ description: "Branch to target when creating a PR against (main, by default)"
+ required: false
+ default: main
+
+outputs:
+ pull_request_id:
+ description: "Pull request ID created"
+ value: ${{ steps.create-pr.outputs.pull_request_id }}
+ temp_branch:
+ description: "Temporary branch created with staged changed"
+ value: ${{ steps.create-pr.outputs.temp_branch }}
+
+runs:
+ using: "composite"
+ steps:
+ - id: adjust-path
+ run: echo "${{ github.action_path }}" >> $GITHUB_PATH
+ shell: bash
+ - id: setup-git
+ name: Git client setup and refresh tip
+ run: |
+ git config --global user.name 'aws-powertools-bot'
+ git config --global user.email '151832416+aws-powertools-bot@users.noreply.github.com'
+ git config pull.rebase true
+ git config remote.origin.url >&-
+ shell: bash
+ - id: create-pr
+ working-directory: ${{ env.GITHUB_WORKSPACE }}
+ run: create_pr_for_staged_changes.sh "${FILES}"
+ env:
+ FILES: ${{ inputs.files }}
+ TEMP_BRANCH_PREFIX: ${{ inputs.temp_branch_prefix }}
+ PR_TITLE: ${{ inputs.pull_request_title }}
+ BASE_BRANCH: ${{ inputs.target_branch }}
+ GH_TOKEN: ${{ inputs.github_token }}
+ shell: bash
+ - id: cleanup
+ name: Cleanup orphaned branch
+ if: failure()
+ run: git push origin --delete "${TEMP_BRANCH_PREFIX}-${GITHUB_RUN_ID}" || echo "Must have failed before creating temporary branch; no cleanup needed."
+ env:
+ TEMP_BRANCH_PREFIX: ${{ inputs.temp_branch_prefix }}
+ GITHUB_RUN_ID: ${{ github.run_id }}
+ shell: bash
diff --git a/.github/actions/create-pr/create_pr_for_staged_changes.sh b/.github/actions/create-pr/create_pr_for_staged_changes.sh
new file mode 100755
index 0000000000..063a2e0b47
--- /dev/null
+++ b/.github/actions/create-pr/create_pr_for_staged_changes.sh
@@ -0,0 +1,148 @@
+#!/bin/bash
+set -uo pipefail # prevent accessing unset env vars, prevent masking pipeline errors to the next command
+
+#docs
+#title :create_pr_for_staged_changes.sh
+#description :This script will create a PR for staged changes, detect and close duplicate PRs. All PRs will be omitted from Release Notes and Changelogs
+#author :@heitorlessa
+#date :May 8th 2023
+#version :0.1
+#usage :bash create_pr_for_staged_changes.sh {git_staged_files_or_directories_separated_by_space}
+#notes :Meant to use in GitHub Actions only. Temporary branch will be named $TEMP_BRANCH_PREFIX-$GITHUB_RUN_ID
+#os_version :Ubuntu 22.04.2 LTS
+#required_env_vars :PR_TITLE, TEMP_BRANCH_PREFIX, GH_TOKEN
+#==============================================================================
+
+# Sets GitHub Action with error message to ease troubleshooting
+function error() {
+ echo "::error file=${FILENAME}::$1"
+ exit 1
+}
+
+function debug() {
+ TIMESTAMP=$(date -u "+%FT%TZ") # 2023-05-10T07:53:59Z
+ echo ""${TIMESTAMP}" - $1"
+}
+
+function notice() {
+ echo "::notice file=${FILENAME}::$1"
+}
+
+function start_span() {
+ echo "::group::$1"
+}
+
+function end_span() {
+ echo "::endgroup::"
+}
+
+function has_required_config() {
+ start_span "Validating required config"
+ test -z "${TEMP_BRANCH_PREFIX}" && error "TEMP_BRANCH_PREFIX env must be set to create a PR"
+ test -z "${PR_TITLE}" && error "PR_TITLE env must be set"
+ test -z "${GH_TOKEN}" && error "GH_TOKEN env must be set for GitHub CLI"
+
+ # Default GitHub Actions Env Vars: https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
+ debug "Are we running in GitHub Action environment?"
+ test -z "${GITHUB_RUN_ID}" && error "GITHUB_RUN_ID env must be set to trace Workflow Run ID back to PR"
+ test -z "${GITHUB_SERVER_URL}" && error "GITHUB_SERVER_URL env must be set to trace Workflow Run ID back to PR"
+ test -z "${GITHUB_REPOSITORY}" && error "GITHUB_REPOSITORY env must be set to trace Workflow Run ID back to PR"
+
+ debug "Config validated successfully!"
+ set_environment_variables
+ end_span
+}
+
+function set_environment_variables() {
+ start_span "Setting environment variables"
+ export readonly WORKFLOW_URL="${GITHUB_SERVER_URL}"/"${GITHUB_REPOSITORY}"/actions/runs/"${GITHUB_RUN_ID}" # e.g., heitorlessa/aws-lambda-powertools-test/actions/runs/4913570678
+ export readonly TEMP_BRANCH="${TEMP_BRANCH_PREFIX}"-"${GITHUB_RUN_ID}" # e.g., ci-changelog-4894658712
+ export readonly BASE_BRANCH="${BASE_BRANCH:-main}" # e.g., main, defaults to develop if missing
+ export readonly PR_BODY="This is an automated PR created from the following workflow"
+ export readonly FILENAME=".github/scripts/$(basename "$0")"
+ export readonly NO_DUPLICATES_MESSAGE="No duplicated PRs found"
+ export readonly SKIP_LABEL="skip-changelog"
+
+ end_span
+}
+
+function has_anything_changed() {
+ start_span "Validating git staged files"
+ HAS_ANY_SOURCE_CODE_CHANGED="$(git status --porcelain)"
+
+ test -z "${HAS_ANY_SOURCE_CODE_CHANGED}" && debug "Nothing to update; exitting early" && exit 0
+ end_span
+}
+
+function create_temporary_branch_with_changes() {
+ start_span "Creating temporary branch: "${TEMP_BRANCH}""
+ git checkout -b "${TEMP_BRANCH}"
+
+ debug "Committing staged files: $*"
+ echo "$@" | xargs -n1 git add || error "Failed to add staged changes: "$@""
+ git commit -m "${PR_TITLE}"
+
+ git push origin "${TEMP_BRANCH}" || error "Failed to create new temporary branch"
+ end_span
+}
+
+function create_pr() {
+ start_span "Creating PR against ${TEMP_BRANCH} branch"
+ # TODO: create label
+ NEW_PR_URL=$(gh pr create --title "${PR_TITLE}" --body "${PR_BODY}: ${WORKFLOW_URL}" --base "${BASE_BRANCH}" --label "${SKIP_LABEL}" || error "Failed to create PR") # e.g, https://github.com/aws-powertools/powertools-lambda-python/pull/13
+
+ # greedy remove any string until the last URL path, including the last '/'. https://opensource.com/article/17/6/bash-parameter-expansion
+ debug "Extracing PR Number from PR URL: "${NEW_PR_URL}""
+ NEW_PR_ID="${NEW_PR_URL##*/}" # 13
+ export NEW_PR_URL
+ export NEW_PR_ID
+ end_span
+}
+
+function close_duplicate_prs() {
+ start_span "Searching for duplicate PRs"
+ DUPLICATE_PRS=$(gh pr list --search "${PR_TITLE}" --json number --jq ".[] | select(.number != ${NEW_PR_ID}) | .number") # e.g, 13\n14
+
+ if [ -z "${DUPLICATE_PRS}" ]; then
+ debug "No duplicate PRs found"
+ DUPLICATE_PRS="${NO_DUPLICATES_MESSAGE}"
+ else
+ debug "Closing duplicated PRs: "${DUPLICATE_PRS}""
+ echo "${DUPLICATE_PRS}" | xargs -L1 gh pr close --delete-branch --comment "Superseded by #${NEW_PR_ID}"
+ fi
+
+ export readonly DUPLICATE_PRS
+ end_span
+}
+
+function report_job_output() {
+ start_span "Updating job outputs"
+ echo pull_request_id="${NEW_PR_ID}" >>"$GITHUB_OUTPUT"
+ echo temp_branch="${TEMP_BRANCH}" >>"$GITHUB_OUTPUT"
+ end_span
+}
+
+function report_summary() {
+ start_span "Creating job summary"
+ echo "### Pull request created successfully :rocket: ${NEW_PR_URL}
Closed duplicated PRs: ${DUPLICATE_PRS}" >>"$GITHUB_STEP_SUMMARY"
+
+ notice "PR_URL is: ${NEW_PR_URL}"
+ notice "PR_BRANCH is: ${TEMP_BRANCH}"
+ notice "PR_DUPLICATES are: ${DUPLICATE_PRS}"
+ end_span
+}
+
+function main() {
+ # Sanity check
+ has_anything_changed
+ has_required_config
+
+ create_temporary_branch_with_changes "$@"
+ create_pr
+ close_duplicate_prs
+
+ report_job_output
+ report_summary
+}
+
+main "$@"
diff --git a/.github/workflows/make-version.yml b/.github/workflows/make-version.yml
new file mode 100644
index 0000000000..4f60ce52be
--- /dev/null
+++ b/.github/workflows/make-version.yml
@@ -0,0 +1,47 @@
+name: Make Version
+
+on:
+ workflow_dispatch: { }
+
+
+env:
+ RELEASE_COMMIT: ${{ github.sha }}
+
+jobs:
+ bump-version:
+ permissions:
+ id-token: write
+ contents: write
+ pull-requests: write
+ runs-on: ubuntu-latest
+ outputs:
+ RELEASE_VERSION: ${{ steps.set-release-version.outputs.RELEASE_VERSION }}
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ github.ref }}
+ - name: Setup NodeJS
+ uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
+ with:
+ node-version: "20"
+ cache: "npm"
+ - name: Setup dependencies
+ uses: ./.github/actions/cached-node-modules
+ - name: Version
+ id: bump-version
+ run: |
+ npx lerna version --conventional-commits --no-git-tag-version --no-push --no-commit-hooks --yes
+ git add .
+ - name: Set release version
+ id: set-release-version
+ run: |
+ VERSION=$(cat lerna.json | jq .version -r)
+ echo RELEASE_VERSION="$VERSION" >> "$GITHUB_OUTPUT"
+ - name: Create PR
+ id: create-pr
+ uses: ./.github/actions/create-pr
+ with:
+ temp_branch_prefix: "ci-bump"
+ pull_request_title: "chore(ci): bump version to ${{ steps.set-release-version.outputs.RELEASE_VERSION }}"
+ github_token: ${{ secrets.GITHUB_TOKEN }}