diff --git a/.github/scripts/create_pr_for_staged_changes.sh b/.github/scripts/create_pr_for_staged_changes.sh
new file mode 100644
index 00000000000..a35d45cc9e9
--- /dev/null
+++ b/.github/scripts/create_pr_for_staged_changes.sh
@@ -0,0 +1,116 @@
+#!/bin/bash
+set -uxo pipefail # enable debugging, 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 and detect and close duplicate PRs.
+#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 :COMMIT_MSG, PR_TITLE, TEMP_BRANCH_PREFIX, GH_TOKEN, GITHUB_RUN_ID, GITHUB_SERVER_URL, GITHUB_REPOSITORY
+#==============================================================================
+
+PR_BODY="This is an automated PR created from the following workflow"
+FILENAME=".github/scripts/$(basename "$0")"
+readonly PR_BODY
+readonly FILENAME
+
+# Sets GitHub Action with error message to ease troubleshooting
+function raise_validation_error() {
+ echo "::error file=${FILENAME}::$1"
+ exit 1
+}
+
+function debug() {
+ echo "::debug::$1"
+}
+
+function notice() {
+ echo "::notice file=${FILENAME}::$1"
+}
+
+function has_required_config() {
+ # Default GitHub Actions Env Vars: https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
+ debug "Do we have required environment variables?"
+ test -z "${TEMP_BRANCH_PREFIX}" && raise_validation_error "TEMP_BRANCH_PREFIX env must be set to create a PR"
+ test -z "${GH_TOKEN}" && raise_validation_error "GH_TOKEN env must be set for GitHub CLI"
+ test -z "${COMMIT_MSG}" && raise_validation_error "COMMIT_MSG env must be set"
+ test -z "${PR_TITLE}" && raise_validation_error "PR_TITLE env must be set"
+ test -z "${GITHUB_RUN_ID}" && raise_validation_error "GITHUB_RUN_ID env must be set to trace Workflow Run ID back to PR"
+ test -z "${GITHUB_SERVER_URL}" && raise_validation_error "GITHUB_SERVER_URL env must be set to trace Workflow Run ID back to PR"
+ test -z "${GITHUB_REPOSITORY}" && raise_validation_error "GITHUB_REPOSITORY env must be set to trace Workflow Run ID back to PR"
+
+ set_environment_variables
+}
+
+function set_environment_variables() {
+ WORKFLOW_URL="${GITHUB_SERVER_URL}"/"${GITHUB_REPOSITORY}"/actions/runs/"${GITHUB_RUN_ID}" # e.g., heitorlessa/aws-lambda-powertools-test/actions/runs/4913570678
+ TEMP_BRANCH="${TEMP_BRANCH_PREFIX}"-"${GITHUB_RUN_ID}" # e.g., ci-changelog-4894658712
+
+ export readonly WORKFLOW_URL
+ export readonly TEMP_BRANCH
+}
+
+function has_anything_changed() {
+ debug "Is there an update to the source code?"
+ HAS_ANY_SOURCE_CODE_CHANGED="$(git status --porcelain)"
+
+ test -z "${HAS_ANY_SOURCE_CODE_CHANGED}" && echo "Nothing to update" && exit 0
+}
+
+function create_temporary_branch_with_changes() {
+ debug "Creating branch ${TEMP_BRANCH}"
+ git checkout -b "${TEMP_BRANCH}"
+
+ debug "Committing staged files: $*"
+ git add "$@"
+ git commit -m "${COMMIT_MSG}"
+
+ debug "Creating branch remotely"
+ git push origin "${TEMP_BRANCH}"
+}
+
+function create_pr() {
+ debug "Creating PR against ${BRANCH} branch"
+ NEW_PR_URL=$(gh pr create --title "${PR_TITLE}" --body "${PR_BODY}: ${WORKFLOW_URL}" --base "${BRANCH}") # e.g, https://github.com/awslabs/aws-lambda-powertools/pull/13
+
+ # greedy remove any string until the last URL path, including the last '/'. https://opensource.com/article/17/6/bash-parameter-expansion
+ NEW_PR_ID="${NEW_PR_URL##*/}" # 13
+ export NEW_PR_URL
+ export NEW_PR_ID
+}
+
+function close_duplicate_prs() {
+ debug "Do we have any duplicate PRs?"
+ DUPLICATE_PRS=$(gh pr list --search "${PR_TITLE}" --json number --jq ".[] | select(.number != ${NEW_PR_ID}) | .number") # e.g, 13\n14
+
+ debug "Closing duplicated PRs if any"
+ echo "${DUPLICATE_PRS}" | xargs -L1 gh pr close --delete-branch --comment "Superseded by #${NEW_PR_ID}"
+ export readonly DUPLICATE_PRS
+}
+
+function report_summary() {
+ debug "Creating job summary"
+ echo "### Pull request created successfully :rocket: #${NEW_PR_URL}
Closed duplicated PRs (if any): ${DUPLICATE_PRS}" >>"$GITHUB_STEP_SUMMARY"
+
+ notice "PR_URL is ${NEW_PR_URL}"
+ notice "PR_BRANCH is ${TEMP_BRANCH}"
+ notice "PR_DUPLICATES are ${DUPLICATE_PRS}"
+}
+
+function main() {
+ # Sanity check
+ has_anything_changed
+ has_required_config
+
+ create_temporary_branch_with_changes "$@"
+ create_pr
+ close_duplicate_prs
+
+ report_summary
+}
+
+main "$@"
diff --git a/.github/workflows/reusable_publish_changelog.yml b/.github/workflows/reusable_publish_changelog.yml
index 2e038eae924..4294dda4a94 100644
--- a/.github/workflows/reusable_publish_changelog.yml
+++ b/.github/workflows/reusable_publish_changelog.yml
@@ -3,9 +3,6 @@ name: Build and publish latest changelog
on:
workflow_call:
-permissions:
- contents: write
-
env:
BRANCH: develop
@@ -16,6 +13,9 @@ jobs:
concurrency:
group: changelog-build
runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
steps:
- name: Checkout repository # reusable workflows start clean, so we need to checkout again
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
@@ -30,11 +30,16 @@ jobs:
git pull origin "${BRANCH}"
- name: "Generate latest changelog"
run: make changelog
- - name: Update Changelog in trunk
- run: |
- HAS_CHANGE=$(git status --porcelain)
- test -z "${HAS_CHANGE}" && echo "Nothing to update" && exit 0
- git add CHANGELOG.md
- git commit -m "update changelog with latest changes"
- git pull origin "${BRANCH}" # prevents concurrent branch update failing push
- git push origin HEAD:refs/heads/"${BRANCH}"
+ - name: Create PR
+ run: bash .github/scripts/create_pr_for_staged_changes.sh CHANGELOG.md
+ env:
+ COMMIT_MSG: "chore(ci): update changelog with latest changes"
+ PR_TITLE: "chore(ci): changelog rebuild"
+ TEMP_BRANCH_PREFIX: "ci-changelog"
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ - 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: "ci-changelog"
+ GITHUB_RUN_ID: ${{ github.run_id }}