From b57f3b079481803b104baec1466b72f7f08a764a Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 11:05:50 +0100 Subject: [PATCH 01/28] feat: add action and som tests --- .github/workflows/release.yml | 59 +++++++++++ .github/workflows/test_action.yml | 24 +++++ .pre-commit-config.yaml | 61 ++++++++++++ action.sh | 115 +++++++++++++++++++++ action.yml | 159 ++++++++++++++++++++++++++++++ 5 files changed, 418 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test_action.yml create mode 100755 .pre-commit-config.yaml create mode 100755 action.sh create mode 100644 action.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..ef9982f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,59 @@ +name: release +on: + push: + branches: + - master + tags: + - 'v*.*.*' + pull_request: + types: + - labeled + +jobs: + release: + if: github.event.action != 'labeled' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # Bump version on merging Pull Requests with specific labels. + # (bump:major,bump:minor,bump:patch) + - id: bumpr + if: "!startsWith(github.ref, 'refs/tags/')" + uses: haya14busa/action-bumpr@v1 + + # Update corresponding major and minor tag. + # e.g. Update v1 and v1.2 when releasing v1.2.3 + - uses: haya14busa/action-update-semver@v1 + if: "!steps.bumpr.outputs.skip" + with: + tag: ${{ steps.bumpr.outputs.next_version }} + + # Get tag name. + - id: tag + uses: haya14busa/action-cond@v1 + with: + cond: "${{ startsWith(github.ref, 'refs/tags/') }}" + if_true: ${{ github.ref }} + if_false: ${{ steps.bumpr.outputs.next_version }} + + # Create release. + - uses: shogo82148/actions-create-release@v1 + if: "steps.tag.outputs.value != ''" + with: + # This token is provided by Actions, you do not + # need to create your own token + github_token: ${{ secrets.GITHUB_TOKEN }} + tag_name: ${{ steps.tag.outputs.value }} + release_name: Release ${{ steps.tag.outputs.value }} + body: ${{ steps.bumpr.outputs.message }} + draft: false + prerelease: false + + release-check: + if: github.event.action == 'labeled' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Post bumpr status comment + uses: haya14busa/action-bumpr@v1 diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml new file mode 100644 index 0000000..0a267ed --- /dev/null +++ b/.github/workflows/test_action.yml @@ -0,0 +1,24 @@ +--- +name: Test Action + +on: [push, workflow_dispatch] + +jobs: + test_action: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + steps: + - uses: actions/checkout@v4 + with: + path: ./action + - uses: actions/checkout@v4 + with: + repository: zckv/semantic-versioning-example + path: ./pyproject + - uses: ./action + with: + root_options: -v + directory: ./pyproject + psr_version: 8.3.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100755 index 0000000..4d4715c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,61 @@ +--- +default_stages: [pre-commit, manual] + +repos: + # fix + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: pretty-format-json + - id: requirements-txt-fixer + - id: trailing-whitespace + stages: [pre-commit, manual] + - id: end-of-file-fixer + stages: [pre-commit, manual] + - id: fix-encoding-pragma + - id: fix-byte-order-marker + + - repo: https://github.com/psf/black + rev: 24.10.0 + hooks: + - id: black + language_version: python3 + + # check + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: name-tests-test + - id: check-added-large-files + - id: check-json + - id: check-toml + - id: check-xml + - id: check-yaml + - id: check-symlinks + - id: check-ast + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.13.0 + hooks: + - id: mypy + args: [--explicit-package-bases] + additional_dependencies: + - types-python-dateutil + - types-flask + - types-requests + + - repo: https://github.com/PyCQA/flake8 + rev: 7.1.1 + hooks: + - id: flake8 + + - repo: https://github.com/adrienverge/yamllint + rev: v1.35.1 + hooks: + - id: yamllint + + - repo: https://github.com/compilerla/conventional-pre-commit + rev: v3.5.0 + hooks: + - id: conventional-pre-commit + stages: [commit-msg] diff --git a/action.sh b/action.sh new file mode 100755 index 0000000..91cee1e --- /dev/null +++ b/action.sh @@ -0,0 +1,115 @@ +#!/bin/bash + +set -ex + +# Convert "true"/"false" into command line args, returns "" if not defined +eval_boolean_action_input() { + local -r input_name="$1" + shift + local -r flag_value="$1" + shift + local -r if_true="$1" + shift + local -r if_false="$1" + + if [ -z "$flag_value" ]; then + echo "" + elif [ "$flag_value" = "true" ]; then + echo "$if_true" + elif [ "$flag_value" = "false" ]; then + echo "$if_false" + else + printf 'Error: Invalid value for input %s: %s is not "true" or "false\n"' \ + "$input_name" "$flag_value" >&2 + return 1 + fi +} + +# Convert inputs to command line arguments +export ARGS=() +# v10 Breaking change as prerelease should be as_prerelease to match +ARGS+=("$(eval_boolean_action_input "prerelease" "$INPUT_PRERELEASE" "--as-prerelease" "")") || exit 1 +ARGS+=("$(eval_boolean_action_input "commit" "$INPUT_COMMIT" "--commit" "--no-commit")") || exit 1 +ARGS+=("$(eval_boolean_action_input "tag" "$INPUT_TAG" "--tag" "--no-tag")") || exit 1 +ARGS+=("$(eval_boolean_action_input "push" "$INPUT_PUSH" "--push" "--no-push")") || exit 1 +ARGS+=("$(eval_boolean_action_input "changelog" "$INPUT_CHANGELOG" "--changelog" "--no-changelog")") || exit 1 +ARGS+=("$(eval_boolean_action_input "vcs_release" "$INPUT_VCS_RELEASE" "--vcs-release" "--no-vcs-release")") || exit 1 +ARGS+=("$(eval_boolean_action_input "build" "$INPUT_BUILD" "" "--skip-build")") || exit 1 + +# Handle --patch, --minor, --major +# https://stackoverflow.com/a/47541882 +valid_force_levels=("prerelease" "patch" "minor" "major") +if [ -z "$INPUT_FORCE" ]; then + true # do nothing if 'force' input is not set +elif printf '%s\0' "${valid_force_levels[@]}" | grep -Fxzq "$INPUT_FORCE"; then + ARGS+=("--$INPUT_FORCE") +else + printf "Error: Input 'force' must be one of: %s\n" "${valid_force_levels[@]}" >&2 +fi + +if [ -n "$INPUT_BUILD_METADATA" ]; then + ARGS+=("--build-metadata $INPUT_BUILD_METADATA") +fi + +if [ -n "$INPUT_PRERELEASE_TOKEN" ]; then + ARGS+=("--prerelease-token $INPUT_PRERELEASE_TOKEN") +fi + +# Change to configured directory +cd "${INPUT_DIRECTORY}" + +# Set Git details +if ! [ "${INPUT_GIT_COMMITTER_NAME:="-"}" = "-" ]; then + git config user.name "$INPUT_GIT_COMMITTER_NAME" +fi +if ! [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" = "-" ]; then + git config user.email "$INPUT_GIT_COMMITTER_EMAIL" +fi +if [ "${INPUT_GIT_COMMITTER_NAME:="-"}" != "-" ] && [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" != "-" ]; then + # Must export this value to the environment for PSR to consume the override + export GIT_COMMIT_AUTHOR="$INPUT_GIT_COMMITTER_NAME <$INPUT_GIT_COMMITTER_EMAIL>" +fi + +# See https://github.com/actions/runner-images/issues/6775#issuecomment-1409268124 +# and https://github.com/actions/runner-images/issues/6775#issuecomment-1410270956 +# NOTE: remove comment ? +# git config --system --add safe.directory "*" + +if [[ -n "$INPUT_SSH_PUBLIC_SIGNING_KEY" && -n "$INPUT_SSH_PRIVATE_SIGNING_KEY" ]]; then + echo "SSH Key pair found, configuring signing..." + + # Write keys to disk + mkdir -vp ~/.ssh + echo -e "$INPUT_SSH_PUBLIC_SIGNING_KEY" >>~/.ssh/signing_key.pub + cat ~/.ssh/signing_key.pub + echo -e "$INPUT_SSH_PRIVATE_SIGNING_KEY" >>~/.ssh/signing_key + # DO NOT CAT private key for security reasons + sha256sum ~/.ssh/signing_key + # Ensure read only private key + chmod 400 ~/.ssh/signing_key + + # Enable ssh-agent & add signing key + eval "$(ssh-agent -s)" + ssh-add ~/.ssh/signing_key + + # Create allowed_signers file for git + if [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" = "-" ]; then + echo >&2 "git_committer_email must be set to use SSH key signing!" + exit 1 + fi + touch ~/.ssh/allowed_signers + echo "$INPUT_GIT_COMMITTER_EMAIL $INPUT_SSH_PUBLIC_SIGNING_KEY" >~/.ssh/allowed_signers + + # Configure git for signing + git config gpg.format ssh + git config gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers + git config user.signingKey ~/.ssh/signing_key + git config commit.gpgsign true + git config tag.gpgsign true +fi + +# Copy inputs into correctly-named environment variables +export GH_TOKEN="${INPUT_GITHUB_TOKEN}" + +# Run Semantic Release (explicitly use the GitHub action version) +eval "~/semantic-release/.venv/bin/semantic-release $INPUT_ROOT_OPTIONS version ${ARGS[*]}" diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..81e274b --- /dev/null +++ b/action.yml @@ -0,0 +1,159 @@ +--- +name: Python Semantic Release Composite Action + +description: Automated Releases via SemVer and Commit Message Conventions + +branding: + color: orange + +inputs: + root_options: + default: "-v" + required: false + description: | + Additional options for the main command. Example: -vv --noop + + directory: + default: "." + required: false + description: Sub-directory to cd into before running semantic-release + + github_token: + type: string + required: true + description: GitHub token used to push release notes and new commits/tags + + git_committer_name: + type: string + required: false + description: The human name for the “committer” field + + git_committer_email: + type: string + required: false + description: The email address for the “committer” field + + ssh_public_signing_key: + type: string + required: false + description: The ssh public key used to sign commits + + ssh_private_signing_key: + type: string + required: false + description: The ssh private key used to sign commits + + # `semantic-release version` command line options + prerelease: + type: string + required: false + description: | + Force the next version to be a prerelease. Set to "true" or "false". + + prerelease_token: + type: string + required: false + description: | + Force the next version to use this prerelease token, + if it is a prerelease. + + force: + type: string + required: false + description: | + Force the next version to be a major release. Must be set to + one of "prerelease", "patch", "minor", or "major". + + commit: + type: string + required: false + description: Whether or not to commit changes locally. Defaults are handled + by python-semantic-release internal version command. + + tag: + type: string + required: false + description: | + Whether or not to make a local version tag. Defaults are handled + by python-semantic-release internal version command. + + push: + type: string + required: false + description: | + Whether or not to push local commits to the Git repository. See + the configuration page for defaults of `semantic-release version` + for how the default is determined between push, tag, & commit. + + changelog: + type: string + required: false + description: | + Whether or not to update the changelog. + + vcs_release: + type: string + required: false + description: | + Whether or not to create a release in the remote VCS, if supported + + build: + type: string + required: false + description: | + Whether or not to run the build_command for the project. Defaults are + handled by python-semantic-release internal version command. + + build_metadata: + type: string + required: false + description: | + Build metadata to append to the new version + + psr_version: + type: string + required: false + description: | + Pin python-semantic-release version to a specific value + +outputs: + is_prerelease: + description: | + "true" if the version is a prerelease, "false" otherwise + + released: + description: | + "true" if a release was made, "false" otherwise + + tag: + description: | + The Git tag corresponding to the version output + + version: + description: | + The newly released version if one was made, otherwise the current version + +runs: + using: "composite" + steps: + # - run: echo "${{ github.action_path }}" >> $GITHUB_PATH + # shell: bash + - name: Prepare PSR environment + run: | + if ! command -v python $> /dev/null + then + echo "Python not found." + exit 1 + fi + python -m venv ~/semantic-release/.venv + source ~/semantic-release/.venv/bin/activate + if [ -z "$INPUT_PSR_VERSION" ] + then + pip install python-semantic-release + else + pip install "python-semantic-release==$INPUT_PSR_VERSION" + fi + shell: bash + - run: action.sh + id: semrel + shell: bash From 0e5de15ab5bc25f270ca2e2d8b0e40e18c329ce7 Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 13:55:15 +0100 Subject: [PATCH 02/28] fix: add directory for lauching script --- action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 81e274b..105b5d4 100644 --- a/action.yml +++ b/action.yml @@ -154,6 +154,7 @@ runs: pip install "python-semantic-release==$INPUT_PSR_VERSION" fi shell: bash - - run: action.sh + - name: Launch PSR action script + run: ./action.sh id: semrel shell: bash From f521f7dab2ebf107912b05fb8ce1c5d0bdded6be Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 15:15:02 +0100 Subject: [PATCH 03/28] feat: put commands in action.yml --- .pre-commit-config.yaml | 1 + action.sh | 115 ---------------------------------------- action.yml | 104 ++++++++++++++++++++++++++++++++---- 3 files changed, 96 insertions(+), 124 deletions(-) delete mode 100755 action.sh diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4d4715c..96a9200 100755 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,6 +53,7 @@ repos: rev: v1.35.1 hooks: - id: yamllint + args: [-d, relaxed] - repo: https://github.com/compilerla/conventional-pre-commit rev: v3.5.0 diff --git a/action.sh b/action.sh deleted file mode 100755 index 91cee1e..0000000 --- a/action.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/bash - -set -ex - -# Convert "true"/"false" into command line args, returns "" if not defined -eval_boolean_action_input() { - local -r input_name="$1" - shift - local -r flag_value="$1" - shift - local -r if_true="$1" - shift - local -r if_false="$1" - - if [ -z "$flag_value" ]; then - echo "" - elif [ "$flag_value" = "true" ]; then - echo "$if_true" - elif [ "$flag_value" = "false" ]; then - echo "$if_false" - else - printf 'Error: Invalid value for input %s: %s is not "true" or "false\n"' \ - "$input_name" "$flag_value" >&2 - return 1 - fi -} - -# Convert inputs to command line arguments -export ARGS=() -# v10 Breaking change as prerelease should be as_prerelease to match -ARGS+=("$(eval_boolean_action_input "prerelease" "$INPUT_PRERELEASE" "--as-prerelease" "")") || exit 1 -ARGS+=("$(eval_boolean_action_input "commit" "$INPUT_COMMIT" "--commit" "--no-commit")") || exit 1 -ARGS+=("$(eval_boolean_action_input "tag" "$INPUT_TAG" "--tag" "--no-tag")") || exit 1 -ARGS+=("$(eval_boolean_action_input "push" "$INPUT_PUSH" "--push" "--no-push")") || exit 1 -ARGS+=("$(eval_boolean_action_input "changelog" "$INPUT_CHANGELOG" "--changelog" "--no-changelog")") || exit 1 -ARGS+=("$(eval_boolean_action_input "vcs_release" "$INPUT_VCS_RELEASE" "--vcs-release" "--no-vcs-release")") || exit 1 -ARGS+=("$(eval_boolean_action_input "build" "$INPUT_BUILD" "" "--skip-build")") || exit 1 - -# Handle --patch, --minor, --major -# https://stackoverflow.com/a/47541882 -valid_force_levels=("prerelease" "patch" "minor" "major") -if [ -z "$INPUT_FORCE" ]; then - true # do nothing if 'force' input is not set -elif printf '%s\0' "${valid_force_levels[@]}" | grep -Fxzq "$INPUT_FORCE"; then - ARGS+=("--$INPUT_FORCE") -else - printf "Error: Input 'force' must be one of: %s\n" "${valid_force_levels[@]}" >&2 -fi - -if [ -n "$INPUT_BUILD_METADATA" ]; then - ARGS+=("--build-metadata $INPUT_BUILD_METADATA") -fi - -if [ -n "$INPUT_PRERELEASE_TOKEN" ]; then - ARGS+=("--prerelease-token $INPUT_PRERELEASE_TOKEN") -fi - -# Change to configured directory -cd "${INPUT_DIRECTORY}" - -# Set Git details -if ! [ "${INPUT_GIT_COMMITTER_NAME:="-"}" = "-" ]; then - git config user.name "$INPUT_GIT_COMMITTER_NAME" -fi -if ! [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" = "-" ]; then - git config user.email "$INPUT_GIT_COMMITTER_EMAIL" -fi -if [ "${INPUT_GIT_COMMITTER_NAME:="-"}" != "-" ] && [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" != "-" ]; then - # Must export this value to the environment for PSR to consume the override - export GIT_COMMIT_AUTHOR="$INPUT_GIT_COMMITTER_NAME <$INPUT_GIT_COMMITTER_EMAIL>" -fi - -# See https://github.com/actions/runner-images/issues/6775#issuecomment-1409268124 -# and https://github.com/actions/runner-images/issues/6775#issuecomment-1410270956 -# NOTE: remove comment ? -# git config --system --add safe.directory "*" - -if [[ -n "$INPUT_SSH_PUBLIC_SIGNING_KEY" && -n "$INPUT_SSH_PRIVATE_SIGNING_KEY" ]]; then - echo "SSH Key pair found, configuring signing..." - - # Write keys to disk - mkdir -vp ~/.ssh - echo -e "$INPUT_SSH_PUBLIC_SIGNING_KEY" >>~/.ssh/signing_key.pub - cat ~/.ssh/signing_key.pub - echo -e "$INPUT_SSH_PRIVATE_SIGNING_KEY" >>~/.ssh/signing_key - # DO NOT CAT private key for security reasons - sha256sum ~/.ssh/signing_key - # Ensure read only private key - chmod 400 ~/.ssh/signing_key - - # Enable ssh-agent & add signing key - eval "$(ssh-agent -s)" - ssh-add ~/.ssh/signing_key - - # Create allowed_signers file for git - if [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" = "-" ]; then - echo >&2 "git_committer_email must be set to use SSH key signing!" - exit 1 - fi - touch ~/.ssh/allowed_signers - echo "$INPUT_GIT_COMMITTER_EMAIL $INPUT_SSH_PUBLIC_SIGNING_KEY" >~/.ssh/allowed_signers - - # Configure git for signing - git config gpg.format ssh - git config gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers - git config user.signingKey ~/.ssh/signing_key - git config commit.gpgsign true - git config tag.gpgsign true -fi - -# Copy inputs into correctly-named environment variables -export GH_TOKEN="${INPUT_GITHUB_TOKEN}" - -# Run Semantic Release (explicitly use the GitHub action version) -eval "~/semantic-release/.venv/bin/semantic-release $INPUT_ROOT_OPTIONS version ${ARGS[*]}" diff --git a/action.yml b/action.yml index 105b5d4..84970d0 100644 --- a/action.yml +++ b/action.yml @@ -45,7 +45,7 @@ inputs: # `semantic-release version` command line options prerelease: - type: string + type: boolean required: false description: | Force the next version to be a prerelease. Set to "true" or "false". @@ -65,20 +65,20 @@ inputs: one of "prerelease", "patch", "minor", or "major". commit: - type: string + type: boolean required: false description: Whether or not to commit changes locally. Defaults are handled by python-semantic-release internal version command. tag: - type: string + type: boolean required: false description: | Whether or not to make a local version tag. Defaults are handled by python-semantic-release internal version command. push: - type: string + type: boolean required: false description: | Whether or not to push local commits to the Git repository. See @@ -86,19 +86,19 @@ inputs: for how the default is determined between push, tag, & commit. changelog: - type: string + type: boolean required: false description: | Whether or not to update the changelog. vcs_release: - type: string + type: boolean required: false description: | Whether or not to create a release in the remote VCS, if supported build: - type: string + type: boolean required: false description: | Whether or not to run the build_command for the project. Defaults are @@ -140,6 +140,7 @@ runs: # shell: bash - name: Prepare PSR environment run: | + set -ex if ! command -v python $> /dev/null then echo "Python not found." @@ -154,7 +155,92 @@ runs: pip install "python-semantic-release==$INPUT_PSR_VERSION" fi shell: bash - - name: Launch PSR action script - run: ./action.sh + - name: PSR action script id: semrel shell: bash + run: | + export PSR_ARGS="" + force_levels=("prerelease" "patch" "minor" "major") + if [ -z "$INPUT_FORCE" ]; then + true # do nothing if 'force' input is not set + elif + echo '%s\0' "${force_levels[@]}" | grep -Fxzq "$INPUT_FORCE" + then + ARGS+=("--$INPUT_FORCE") + else + echo "Error: Input 'force' must be one of: %s" >&2 + echo "${force_levels[@]}" >&2 + fi + + if [ -n "$INPUT_BUILD_METADATA" ]; then + ARGS+=("--build-metadata $INPUT_BUILD_METADATA") + fi + + if [ -n "$INPUT_PRERELEASE_TOKEN" ]; then + ARGS+=("--prerelease-token $INPUT_PRERELEASE_TOKEN") + fi + + # Change to configured directory + cd "${INPUT_DIRECTORY}" + + # Set Git details + if ! [ "${INPUT_GIT_COMMITTER_NAME:="-"}" = "-" ]; then + git config user.name "$INPUT_GIT_COMMITTER_NAME" + fi + if ! [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" = "-" ]; then + git config user.email "$INPUT_GIT_COMMITTER_EMAIL" + fi + if ( + [ "${INPUT_GIT_COMMITTER_NAME:="-"}" != "-" ] && + [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" != "-" ] + ); + then + # Must export this value to the environment for PSR to consume the override + export GIT_COMMIT_AUTHOR="$INPUT_GIT_COMMITTER_NAME <$INPUT_GIT_COMMITTER_EMAIL>" + fi + + # See https://github.com/actions/runner-images/issues/6775#issuecomment-1409268124 + # and https://github.com/actions/runner-images/issues/6775#issuecomment-1410270956 + # git config --system --add safe.directory "*" + + if ( + [[n "$INPUT_SSH_PUBLIC_SIGNING_KEY" && + -n "$INPUT_SSH_PRIVATE_SIGNING_KEY" ]] + ); + then + echo "SSH Key pair found, configuring signing..." + + # Write keys to disk + mkdir -vp ~/.ssh + echo -e "$INPUT_SSH_PUBLIC_SIGNING_KEY" >>~/.ssh/signing_key.pub + cat ~/.ssh/signing_key.pub + echo -e "$INPUT_SSH_PRIVATE_SIGNING_KEY" >>~/.ssh/signing_key + # DO NOT CAT private key for security reasons + sha256sum ~/.ssh/signing_key + # Ensure read only private key + chmod 400 ~/.ssh/signing_key + + # Enable ssh-agent & add signing key + eval "$(ssh-agent -s)" + ssh-add ~/.ssh/signing_key + + # Create allowed_signers file for git + if [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" = "-" ]; then + echo >&2 "git_committer_email must be set to use SSH key signing!" + exit 1 + fi + touch ~/.ssh/allowed_signers + echo "$INPUT_GIT_COMMITTER_EMAIL $INPUT_SSH_PUBLIC_SIGNING_KEY" >~/.ssh/allowed_signers + + # Configure git for signing + git config gpg.format ssh + git config gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers + git config user.signingKey ~/.ssh/signing_key + git config commit.gpgsign true + git config tag.gpgsign true + fi + + # Copy inputs into correctly-named environment variables + export GH_TOKEN="${INPUT_GITHUB_TOKEN}" + + semantic-release $INPUT_ROOT_OPTIONS version ${ARGS[*]}" From 8d5d0a2607054fdaae6eb920032b728b2ce9fe54 Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 15:17:33 +0100 Subject: [PATCH 04/28] feat: put commands in action.yml --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 84970d0..a087890 100644 --- a/action.yml +++ b/action.yml @@ -204,7 +204,7 @@ runs: # git config --system --add safe.directory "*" if ( - [[n "$INPUT_SSH_PUBLIC_SIGNING_KEY" && + [[ -n "$INPUT_SSH_PUBLIC_SIGNING_KEY" && -n "$INPUT_SSH_PRIVATE_SIGNING_KEY" ]] ); then @@ -243,4 +243,4 @@ runs: # Copy inputs into correctly-named environment variables export GH_TOKEN="${INPUT_GITHUB_TOKEN}" - semantic-release $INPUT_ROOT_OPTIONS version ${ARGS[*]}" + semantic-release "$INPUT_ROOT_OPTIONS" version "${PSR_ARGS[*]}" From c95a4d2bd1b12c8c2bb6a3d9fa66cd5b775e0cab Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 15:21:47 +0100 Subject: [PATCH 05/28] feat: put commands in action.yml --- action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yml b/action.yml index a087890..fe12165 100644 --- a/action.yml +++ b/action.yml @@ -243,4 +243,6 @@ runs: # Copy inputs into correctly-named environment variables export GH_TOKEN="${INPUT_GITHUB_TOKEN}" + source ~/semantic-release/.venv/bin/activate + env semantic-release "$INPUT_ROOT_OPTIONS" version "${PSR_ARGS[*]}" From e49c005bb7ecf056de2c17cd2629ceda8ac3e833 Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 16:21:47 +0100 Subject: [PATCH 06/28] fix: remove quote --- action.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/action.yml b/action.yml index fe12165..7ae39e1 100644 --- a/action.yml +++ b/action.yml @@ -244,5 +244,4 @@ runs: export GH_TOKEN="${INPUT_GITHUB_TOKEN}" source ~/semantic-release/.venv/bin/activate - env - semantic-release "$INPUT_ROOT_OPTIONS" version "${PSR_ARGS[*]}" + semantic-release $INPUT_ROOT_OPTIONS version ${PSR_ARGS[*]} From c445d4670c6ddd1c94959cd90272eb5b399cf77d Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 16:31:37 +0100 Subject: [PATCH 07/28] chore: debug --- action.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 7ae39e1..462643f 100644 --- a/action.yml +++ b/action.yml @@ -159,7 +159,18 @@ runs: id: semrel shell: bash run: | - export PSR_ARGS="" + set -eux + export ARGS="" + echo "$INPUT_COMMIT" + ARGS+=("$(eval_boolean_action_input "prerelease" "$INPUT_PRERELEASE" "--as-prerelease" "")") || exit 1 + ARGS+=("$(eval_boolean_action_input "commit" "$INPUT_COMMIT" "--commit" "--no-commit")") || exit 1 + + ARGS+=("$(eval_boolean_action_input "tag" "$INPUT_TAG" "--tag" "--no-tag")") || exit 1 + ARGS+=("$(eval_boolean_action_input "push" "$INPUT_PUSH" "--push" "--no-push")") || exit 1 + ARGS+=("$(eval_boolean_action_input "changelog" "$INPUT_CHANGELOG" "--changelog" "--no-changelog")") || exit 1 + ARGS+=("$(eval_boolean_action_input "vcs_release" "$INPUT_VCS_RELEASE" "--vcs-release" "--no-vcs-release")") || exit 1 + ARGS+=("$(eval_boolean_action_input "build" "$INPUT_BUILD" "" "--skip-build")") || exit 1 + force_levels=("prerelease" "patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set @@ -244,4 +255,4 @@ runs: export GH_TOKEN="${INPUT_GITHUB_TOKEN}" source ~/semantic-release/.venv/bin/activate - semantic-release $INPUT_ROOT_OPTIONS version ${PSR_ARGS[*]} + semantic-release $INPUT_ROOT_OPTIONS version ${ARGS[*]} From 38ca5fe61cff1406cf758f80f1c2f3e0741657f5 Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 16:32:57 +0100 Subject: [PATCH 08/28] chore: debug --- .github/workflows/test_action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index 0a267ed..6cdf6c1 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -21,4 +21,5 @@ jobs: with: root_options: -v directory: ./pyproject + commit: false psr_version: 8.3.0 From a683d0f053c2a64847b360ebe8f8237a4cd76130 Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 16:35:17 +0100 Subject: [PATCH 09/28] chore: debug --- .github/workflows/test_action.yml | 1 + action.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index 6cdf6c1..e46b446 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -22,4 +22,5 @@ jobs: root_options: -v directory: ./pyproject commit: false + tag: true psr_version: 8.3.0 diff --git a/action.yml b/action.yml index 462643f..00b1016 100644 --- a/action.yml +++ b/action.yml @@ -159,7 +159,7 @@ runs: id: semrel shell: bash run: | - set -eux + set -ex export ARGS="" echo "$INPUT_COMMIT" ARGS+=("$(eval_boolean_action_input "prerelease" "$INPUT_PRERELEASE" "--as-prerelease" "")") || exit 1 From 47d402e570e7df14ee8f3ff05d4bd18e0838378b Mon Sep 17 00:00:00 2001 From: zckv Date: Thu, 2 Jan 2025 16:49:15 +0100 Subject: [PATCH 10/28] chore: debug --- action.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/action.yml b/action.yml index 00b1016..940b408 100644 --- a/action.yml +++ b/action.yml @@ -162,14 +162,17 @@ runs: set -ex export ARGS="" echo "$INPUT_COMMIT" - ARGS+=("$(eval_boolean_action_input "prerelease" "$INPUT_PRERELEASE" "--as-prerelease" "")") || exit 1 - ARGS+=("$(eval_boolean_action_input "commit" "$INPUT_COMMIT" "--commit" "--no-commit")") || exit 1 - - ARGS+=("$(eval_boolean_action_input "tag" "$INPUT_TAG" "--tag" "--no-tag")") || exit 1 - ARGS+=("$(eval_boolean_action_input "push" "$INPUT_PUSH" "--push" "--no-push")") || exit 1 - ARGS+=("$(eval_boolean_action_input "changelog" "$INPUT_CHANGELOG" "--changelog" "--no-changelog")") || exit 1 - ARGS+=("$(eval_boolean_action_input "vcs_release" "$INPUT_VCS_RELEASE" "--vcs-release" "--no-vcs-release")") || exit 1 - ARGS+=("$(eval_boolean_action_input "build" "$INPUT_BUILD" "" "--skip-build")") || exit 1 + echo "$INPUT_TAG" + [ -z "$INPUT_PRERELEASE" ] && ARGS+="--as-prerelease" || ARGS+="" + [ -z "$INPUT_COMMIT" ] && ARGS+="--commit" || ARGS+="--no_commit" + + [ -z "$INPUT_" ] && ARGS+="" || ARGS+="" + + [ -z "$INPUT_TAG" ] && ARGS+="--tag" || ARGS+="--no-tag" + [ -z "$INPUT_PUSH" ] && ARGS+="--push" || ARGS+="--no-push" + [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog" || ARGS+="--no-changelog" + [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release" || ARGS+="--no-vcs-release" + [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build" force_levels=("prerelease" "patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then From ac59264a14cb510d8b6d70c52ea0e78214471897 Mon Sep 17 00:00:00 2001 From: zckv Date: Fri, 3 Jan 2025 11:23:13 +0100 Subject: [PATCH 11/28] fix: add space --- action.yml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/action.yml b/action.yml index 940b408..be19942 100644 --- a/action.yml +++ b/action.yml @@ -161,18 +161,14 @@ runs: run: | set -ex export ARGS="" - echo "$INPUT_COMMIT" - echo "$INPUT_TAG" - [ -z "$INPUT_PRERELEASE" ] && ARGS+="--as-prerelease" || ARGS+="" - [ -z "$INPUT_COMMIT" ] && ARGS+="--commit" || ARGS+="--no_commit" + [ -z "$INPUT_PRERELEASE" ] && ARGS+="--as-prerelease " || ARGS+="" + [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no_commit " - [ -z "$INPUT_" ] && ARGS+="" || ARGS+="" - - [ -z "$INPUT_TAG" ] && ARGS+="--tag" || ARGS+="--no-tag" - [ -z "$INPUT_PUSH" ] && ARGS+="--push" || ARGS+="--no-push" - [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog" || ARGS+="--no-changelog" - [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release" || ARGS+="--no-vcs-release" - [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build" + [ -z "$INPUT_TAG" ] && ARGS+="--tag " || ARGS+="--no-tag " + [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " + [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " + [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " + [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build " force_levels=("prerelease" "patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then @@ -258,4 +254,4 @@ runs: export GH_TOKEN="${INPUT_GITHUB_TOKEN}" source ~/semantic-release/.venv/bin/activate - semantic-release $INPUT_ROOT_OPTIONS version ${ARGS[*]} + semantic-release $INPUT_ROOT_OPTIONS version $ARGS[*] From ee05380f392c4061dca27feeb6a03c552296ced1 Mon Sep 17 00:00:00 2001 From: zckv Date: Fri, 3 Jan 2025 11:44:22 +0100 Subject: [PATCH 12/28] fix: remove star --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index be19942..b9c9d09 100644 --- a/action.yml +++ b/action.yml @@ -254,4 +254,4 @@ runs: export GH_TOKEN="${INPUT_GITHUB_TOKEN}" source ~/semantic-release/.venv/bin/activate - semantic-release $INPUT_ROOT_OPTIONS version $ARGS[*] + semantic-release $INPUT_ROOT_OPTIONS version $ARGS From 5f46a1f5144a4dbd1b39cbc46a59ef8807149650 Mon Sep 17 00:00:00 2001 From: zckv Date: Fri, 3 Jan 2025 11:56:50 +0100 Subject: [PATCH 13/28] feat: test with removed line --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index b9c9d09..3fe2188 100644 --- a/action.yml +++ b/action.yml @@ -136,8 +136,8 @@ outputs: runs: using: "composite" steps: - # - run: echo "${{ github.action_path }}" >> $GITHUB_PATH - # shell: bash + - run: echo "${{ github.action_path }}" >> $GITHUB_PATH + shell: bash - name: Prepare PSR environment run: | set -ex From 2c0c860fbf7ba7f6b4aea87fef953fc53ad9820d Mon Sep 17 00:00:00 2001 From: zckv Date: Fri, 3 Jan 2025 15:46:31 +0100 Subject: [PATCH 14/28] feat: test with removed line --- action.yml | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/action.yml b/action.yml index 3fe2188..6189cc6 100644 --- a/action.yml +++ b/action.yml @@ -136,11 +136,11 @@ outputs: runs: using: "composite" steps: - - run: echo "${{ github.action_path }}" >> $GITHUB_PATH - shell: bash - name: Prepare PSR environment + env: + INPUT_PSR_VERSION: ${{ inputs.psr_version }} run: | - set -ex + set -eux if ! command -v python $> /dev/null then echo "Python not found." @@ -158,8 +158,26 @@ runs: - name: PSR action script id: semrel shell: bash + env: + INPUT_ROOT_OPTIONS: ${{ inputs.root_options }} + INPUT_DIRECTORY: ${{ inputs.directory }} + INPUT_GITHUB_TOKEN: ${{ inputs.github_token }} + INPUT_GIT_COMMITTER_NAME: ${{ inputs.git_committer_name }} + INPUT_GIT_COMMITTER_EMAIL: ${{ inputs.git_committer_email }} + INPUT_SSH_PUBLIC_SIGNING_KEY: ${{ inputs.ssh_public_signing_key }} + INPUT_SSH_PRIVATE_SIGNING_KEY: ${{ inputs.ssh_private_signing_key }} + INPUT_PRERELEASE: ${{ inputs.prerelease }} + INPUT_PRERELEASE_TOKEN: ${{ inputs.prerelease_token }} + INPUT_FORCE: ${{ inputs.force }} + INPUT_COMMIT: ${{ inputs.commit }} + INPUT_TAG: ${{ inputs.tag }} + INPUT_PUSH: ${{ inputs.push }} + INPUT_CHANGELOG: ${{ inputs.changelog }} + INPUT_VCS_RELEASE: ${{ inputs.vcs_release }} + INPUT_BUILD: ${{ inputs.build }} + INPUT_BUILD_METADATA: ${{ inputs.build_metadata }} run: | - set -ex + set -eux export ARGS="" [ -z "$INPUT_PRERELEASE" ] && ARGS+="--as-prerelease " || ARGS+="" [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no_commit " @@ -176,14 +194,14 @@ runs: elif echo '%s\0' "${force_levels[@]}" | grep -Fxzq "$INPUT_FORCE" then - ARGS+=("--$INPUT_FORCE") + ARGS+="--$INPUT_FORCE " else echo "Error: Input 'force' must be one of: %s" >&2 echo "${force_levels[@]}" >&2 fi if [ -n "$INPUT_BUILD_METADATA" ]; then - ARGS+=("--build-metadata $INPUT_BUILD_METADATA") + ARGS+="--build-metadata $INPUT_BUILD_METADATA " fi if [ -n "$INPUT_PRERELEASE_TOKEN" ]; then From a05854530a7103321bcda49c1853440b7befca4a Mon Sep 17 00:00:00 2001 From: zckv Date: Tue, 14 Jan 2025 10:21:52 +0100 Subject: [PATCH 15/28] fix: underscore in no commit --- .github/workflows/test_action.yml | 3 +++ action.yml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index e46b446..0decdd4 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -10,6 +10,9 @@ jobs: matrix: python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} - uses: actions/checkout@v4 with: path: ./action diff --git a/action.yml b/action.yml index 6189cc6..c199833 100644 --- a/action.yml +++ b/action.yml @@ -180,7 +180,7 @@ runs: set -eux export ARGS="" [ -z "$INPUT_PRERELEASE" ] && ARGS+="--as-prerelease " || ARGS+="" - [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no_commit " + [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no-commit " [ -z "$INPUT_TAG" ] && ARGS+="--tag " || ARGS+="--no-tag " [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " From efcc91ce8dec750cd7e920a0c199cc2553777a8b Mon Sep 17 00:00:00 2001 From: zckv Date: Tue, 14 Jan 2025 10:34:26 +0100 Subject: [PATCH 16/28] chore: use my token --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef9982f..2b92285 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: with: # This token is provided by Actions, you do not # need to create your own token - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.PAT_TOKEN }} tag_name: ${{ steps.tag.outputs.value }} release_name: Release ${{ steps.tag.outputs.value }} body: ${{ steps.bumpr.outputs.message }} From 0d776b4539fa26a21cfc77edad38753324db7f29 Mon Sep 17 00:00:00 2001 From: zckv Date: Tue, 14 Jan 2025 11:30:13 +0100 Subject: [PATCH 17/28] feat: use case switch for compat between versions --- .github/workflows/test_action.yml | 1 + action.yml | 80 +++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index 0decdd4..e0811bd 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -22,6 +22,7 @@ jobs: path: ./pyproject - uses: ./action with: + github_token: ${{ secrets.PAT_TOKEN }} root_options: -v directory: ./pyproject commit: false diff --git a/action.yml b/action.yml index c199833..edb338a 100644 --- a/action.yml +++ b/action.yml @@ -176,37 +176,65 @@ runs: INPUT_VCS_RELEASE: ${{ inputs.vcs_release }} INPUT_BUILD: ${{ inputs.build }} INPUT_BUILD_METADATA: ${{ inputs.build_metadata }} + INPUT_PSR_VERSION: ${{ inputs.psr_version }} run: | set -eux export ARGS="" - [ -z "$INPUT_PRERELEASE" ] && ARGS+="--as-prerelease " || ARGS+="" - [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no-commit " - - [ -z "$INPUT_TAG" ] && ARGS+="--tag " || ARGS+="--no-tag " - [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " - [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " - [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " - [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build " - - force_levels=("prerelease" "patch" "minor" "major") - if [ -z "$INPUT_FORCE" ]; then - true # do nothing if 'force' input is not set - elif - echo '%s\0' "${force_levels[@]}" | grep -Fxzq "$INPUT_FORCE" - then - ARGS+="--$INPUT_FORCE " - else - echo "Error: Input 'force' must be one of: %s" >&2 - echo "${force_levels[@]}" >&2 - fi + case $(echo "$INPUT_PSR_VERSION" | cut -d '.' -f1) in + "9") + [ -z "$INPUT_PRERELEASE" ] && ARGS+="--as-prerelease " || ARGS+="" + [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no-commit " + [ -z "$INPUT_TAG" ] && ARGS+="--tag " || ARGS+="--no-tag " + [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " + [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " + [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " + [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build " + force_levels=("prerelease" "patch" "minor" "major") + if [ -z "$INPUT_FORCE" ]; then + true # do nothing if 'force' input is not set + elif + echo '%s\0' "${force_levels[@]}" | grep -Fxzq "$INPUT_FORCE" + then + ARGS+="--$INPUT_FORCE " + else + echo "Error: Input 'force' must be one of: %s" >&2 + echo "${force_levels[@]}" >&2 + fi - if [ -n "$INPUT_BUILD_METADATA" ]; then - ARGS+="--build-metadata $INPUT_BUILD_METADATA " - fi + if [ -n "$INPUT_BUILD_METADATA" ]; then + ARGS+="--build-metadata $INPUT_BUILD_METADATA " + fi + + if [ -n "$INPUT_PRERELEASE_TOKEN" ]; then + ARGS+=("--prerelease-token $INPUT_PRERELEASE_TOKEN") + fi + ;; + "8") + [ -z "$INPUT_PRERELEASE" ] && ARGS+="--prerelease " || ARGS+="" + [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no-commit " + [ -z "$INPUT_TAG" ] && ARGS+="--tag " || ARGS+="--no-tag " + [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " + [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " + [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " + [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build " + force_levels=("patch" "minor" "major") + if [ -z "$INPUT_FORCE" ]; then + true # do nothing if 'force' input is not set + elif + echo '%s\0' "${force_levels[@]}" | grep -Fxzq "$INPUT_FORCE" + then + ARGS+="--$INPUT_FORCE " + else + echo "Error: Input 'force' must be one of: %s" >&2 + echo "${force_levels[@]}" >&2 + fi + + if [ -n "$INPUT_BUILD_METADATA" ]; then + ARGS+="--build-metadata $INPUT_BUILD_METADATA " + fi + ;; + esac - if [ -n "$INPUT_PRERELEASE_TOKEN" ]; then - ARGS+=("--prerelease-token $INPUT_PRERELEASE_TOKEN") - fi # Change to configured directory cd "${INPUT_DIRECTORY}" From d13bc0d1bea1a085b585f950a8590d6945be57e9 Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 15:49:24 +0100 Subject: [PATCH 18/28] fix: remove tag from version 8 --- action.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/action.yml b/action.yml index edb338a..52917ab 100644 --- a/action.yml +++ b/action.yml @@ -212,11 +212,9 @@ runs: "8") [ -z "$INPUT_PRERELEASE" ] && ARGS+="--prerelease " || ARGS+="" [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no-commit " - [ -z "$INPUT_TAG" ] && ARGS+="--tag " || ARGS+="--no-tag " [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " - [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build " force_levels=("patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set From 8ea91cfb9780f099646726c540c4e028a1a8d705 Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 15:55:24 +0100 Subject: [PATCH 19/28] feat: add noop option --- .github/workflows/test_action.yml | 1 + action.yml | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index e0811bd..2dffe20 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -28,3 +28,4 @@ jobs: commit: false tag: true psr_version: 8.3.0 + noop: true diff --git a/action.yml b/action.yml index 52917ab..2403068 100644 --- a/action.yml +++ b/action.yml @@ -116,6 +116,11 @@ inputs: description: | Pin python-semantic-release version to a specific value + noop: + type: boolean + required: false + description: If true, no operation is made. This is a debug utility. + outputs: is_prerelease: description: | @@ -177,6 +182,7 @@ runs: INPUT_BUILD: ${{ inputs.build }} INPUT_BUILD_METADATA: ${{ inputs.build_metadata }} INPUT_PSR_VERSION: ${{ inputs.psr_version }} + INPUT_NOOP: ${{ inputs.noop }} run: | set -eux export ARGS="" @@ -189,6 +195,7 @@ runs: [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build " + [ -z "$INPUT_NOOP" ] && ARGS+="--noop " || ARGS+="" force_levels=("prerelease" "patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set @@ -215,6 +222,7 @@ runs: [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " + [ -z "$INPUT_NOOP" ] && ARGS+="--noop " || ARGS+="" force_levels=("patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set From 3c4d97e889ce7367939dcf2e876eaa3e8c5853dd Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 16:01:58 +0100 Subject: [PATCH 20/28] chore: debug noop --- action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/action.yml b/action.yml index 2403068..871b849 100644 --- a/action.yml +++ b/action.yml @@ -146,6 +146,7 @@ runs: INPUT_PSR_VERSION: ${{ inputs.psr_version }} run: | set -eux + env if ! command -v python $> /dev/null then echo "Python not found." From 46a0c22b29bdb02112d6e3eb250b8fb85547b58b Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 16:29:02 +0100 Subject: [PATCH 21/28] fix: add bool conversion --- action.yml | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/action.yml b/action.yml index 871b849..aa5bc3d 100644 --- a/action.yml +++ b/action.yml @@ -185,18 +185,30 @@ runs: INPUT_PSR_VERSION: ${{ inputs.psr_version }} INPUT_NOOP: ${{ inputs.noop }} run: | + bool() { + input="$1" + if [ -z "$flag_value" ]; then + return 0 + elif [ "$flag_value" = "true" ]; then + return 0 + elif [ "$flag_value" = "false" ]; then + return 1 + else + return 1 + fi + } set -eux export ARGS="" case $(echo "$INPUT_PSR_VERSION" | cut -d '.' -f1) in "9") - [ -z "$INPUT_PRERELEASE" ] && ARGS+="--as-prerelease " || ARGS+="" - [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no-commit " - [ -z "$INPUT_TAG" ] && ARGS+="--tag " || ARGS+="--no-tag " - [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " - [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " - [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " - [ -z "$INPUT_BUILD" ] && ARGS+="" || ARGS+="--skip-build " - [ -z "$INPUT_NOOP" ] && ARGS+="--noop " || ARGS+="" + bool("$INPUT_PRERELEASE") && ARGS+="--as-prerelease " || ARGS+="" + bool("$INPUT_COMMIT") && ARGS+="--commit " || ARGS+="--no-commit " + bool("$INPUT_TAG") && ARGS+="--tag " || ARGS+="--no-tag " + bool("$INPUT_PUSH") && ARGS+="--push " || ARGS+="--no-push " + bool("$INPUT_CHANGELOG") && ARGS+="--changelog " || ARGS+="--no-changelog " + bool("$INPUT_VCS_RELEASE") && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " + bool("$INPUT_BUILD") && ARGS+="" || ARGS+="--skip-build " + bool("$INPUT_NOOP") && ARGS+="--noop " || ARGS+="" force_levels=("prerelease" "patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set @@ -218,12 +230,12 @@ runs: fi ;; "8") - [ -z "$INPUT_PRERELEASE" ] && ARGS+="--prerelease " || ARGS+="" - [ -z "$INPUT_COMMIT" ] && ARGS+="--commit " || ARGS+="--no-commit " - [ -z "$INPUT_PUSH" ] && ARGS+="--push " || ARGS+="--no-push " - [ -z "$INPUT_CHANGELOG" ] && ARGS+="--changelog " || ARGS+="--no-changelog " - [ -z "$INPUT_VCS_RELEASE" ] && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " - [ -z "$INPUT_NOOP" ] && ARGS+="--noop " || ARGS+="" + bool("$INPUT_PRERELEASE") && ARGS+="--prerelease " || ARGS+="" + bool( "$INPUT_COMMIT") && ARGS+="--commit " || ARGS+="--no-commit " + bool( "$INPUT_PUSH") && ARGS+="--push " || ARGS+="--no-push " + bool( "$INPUT_CHANGELOG") && ARGS+="--changelog " || ARGS+="--no-changelog " + bool( "$INPUT_VCS_RELEASE") && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " + bool( "$INPUT_NOOP") && ARGS+="--noop " || ARGS+="" force_levels=("patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set From 027d69fbe3fbda30b3e1f5be1f845e20191ae1cd Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 16:39:42 +0100 Subject: [PATCH 22/28] fix: correct bool cast function --- action.yml | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/action.yml b/action.yml index aa5bc3d..b821537 100644 --- a/action.yml +++ b/action.yml @@ -119,8 +119,10 @@ inputs: noop: type: boolean required: false + default: false description: If true, no operation is made. This is a debug utility. + outputs: is_prerelease: description: | @@ -187,11 +189,11 @@ runs: run: | bool() { input="$1" - if [ -z "$flag_value" ]; then + if [ -z "$input" ]; then return 0 - elif [ "$flag_value" = "true" ]; then + elif [ "$input" = "true" ]; then return 0 - elif [ "$flag_value" = "false" ]; then + elif [ "$input" = "false" ]; then return 1 else return 1 @@ -201,14 +203,14 @@ runs: export ARGS="" case $(echo "$INPUT_PSR_VERSION" | cut -d '.' -f1) in "9") - bool("$INPUT_PRERELEASE") && ARGS+="--as-prerelease " || ARGS+="" - bool("$INPUT_COMMIT") && ARGS+="--commit " || ARGS+="--no-commit " - bool("$INPUT_TAG") && ARGS+="--tag " || ARGS+="--no-tag " - bool("$INPUT_PUSH") && ARGS+="--push " || ARGS+="--no-push " - bool("$INPUT_CHANGELOG") && ARGS+="--changelog " || ARGS+="--no-changelog " - bool("$INPUT_VCS_RELEASE") && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " - bool("$INPUT_BUILD") && ARGS+="" || ARGS+="--skip-build " - bool("$INPUT_NOOP") && ARGS+="--noop " || ARGS+="" + bool "$INPUT_PRERELEASE" && ARGS+="--as-prerelease " || ARGS+="" + bool "$INPUT_COMMIT" && ARGS+="--commit " || ARGS+="--no-commit " + bool "$INPUT_TAG" && ARGS+="--tag " || ARGS+="--no-tag " + bool "$INPUT_PUSH" && ARGS+="--push " || ARGS+="--no-push " + bool "$INPUT_CHANGELOG" && ARGS+="--changelog " || ARGS+="--no-changelog " + bool "$INPUT_VCS_RELEASE" && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " + bool "$INPUT_BUILD" && ARGS+="" || ARGS+="--skip-build " + bool "$INPUT_NOOP" && ARGS+="--noop " || ARGS+="" force_levels=("prerelease" "patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set @@ -230,12 +232,12 @@ runs: fi ;; "8") - bool("$INPUT_PRERELEASE") && ARGS+="--prerelease " || ARGS+="" - bool( "$INPUT_COMMIT") && ARGS+="--commit " || ARGS+="--no-commit " - bool( "$INPUT_PUSH") && ARGS+="--push " || ARGS+="--no-push " - bool( "$INPUT_CHANGELOG") && ARGS+="--changelog " || ARGS+="--no-changelog " - bool( "$INPUT_VCS_RELEASE") && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " - bool( "$INPUT_NOOP") && ARGS+="--noop " || ARGS+="" + bool "$INPUT_PRERELEASE" && ARGS+="--prerelease " || ARGS+="" + bool "$INPUT_COMMIT" && ARGS+="--commit " || ARGS+="--no-commit " + bool "$INPUT_PUSH" && ARGS+="--push " || ARGS+="--no-push " + bool "$INPUT_CHANGELOG" && ARGS+="--changelog " || ARGS+="--no-changelog " + bool "$INPUT_VCS_RELEASE" && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " + bool "$INPUT_NOOP" && ARGS+="--noop " || ARGS+="" force_levels=("patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set From f742ccd66a2309d34bf7db6edddb584032ff9592 Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 16:48:28 +0100 Subject: [PATCH 23/28] fix: remove noop --- .github/workflows/test_action.yml | 3 +-- action.yml | 12 +----------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index 2dffe20..6cb0b65 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -23,9 +23,8 @@ jobs: - uses: ./action with: github_token: ${{ secrets.PAT_TOKEN }} - root_options: -v + root_options: -v --noop directory: ./pyproject commit: false tag: true psr_version: 8.3.0 - noop: true diff --git a/action.yml b/action.yml index b821537..fc7e817 100644 --- a/action.yml +++ b/action.yml @@ -116,13 +116,6 @@ inputs: description: | Pin python-semantic-release version to a specific value - noop: - type: boolean - required: false - default: false - description: If true, no operation is made. This is a debug utility. - - outputs: is_prerelease: description: | @@ -185,7 +178,6 @@ runs: INPUT_BUILD: ${{ inputs.build }} INPUT_BUILD_METADATA: ${{ inputs.build_metadata }} INPUT_PSR_VERSION: ${{ inputs.psr_version }} - INPUT_NOOP: ${{ inputs.noop }} run: | bool() { input="$1" @@ -210,7 +202,6 @@ runs: bool "$INPUT_CHANGELOG" && ARGS+="--changelog " || ARGS+="--no-changelog " bool "$INPUT_VCS_RELEASE" && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " bool "$INPUT_BUILD" && ARGS+="" || ARGS+="--skip-build " - bool "$INPUT_NOOP" && ARGS+="--noop " || ARGS+="" force_levels=("prerelease" "patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set @@ -237,14 +228,13 @@ runs: bool "$INPUT_PUSH" && ARGS+="--push " || ARGS+="--no-push " bool "$INPUT_CHANGELOG" && ARGS+="--changelog " || ARGS+="--no-changelog " bool "$INPUT_VCS_RELEASE" && ARGS+="--vcs-release " || ARGS+="--no-vcs-release " - bool "$INPUT_NOOP" && ARGS+="--noop " || ARGS+="" force_levels=("patch" "minor" "major") if [ -z "$INPUT_FORCE" ]; then true # do nothing if 'force' input is not set elif echo '%s\0' "${force_levels[@]}" | grep -Fxzq "$INPUT_FORCE" then - ARGS+="--$INPUT_FORCE " + args+="--$input_force " else echo "Error: Input 'force' must be one of: %s" >&2 echo "${force_levels[@]}" >&2 From 1888deaf3b116ba03cbcca41c6dfab678492c0e1 Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 16:51:27 +0100 Subject: [PATCH 24/28] chore: try using older version --- .github/workflows/test_action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index 6cb0b65..2685e6e 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -27,4 +27,4 @@ jobs: directory: ./pyproject commit: false tag: true - psr_version: 8.3.0 + psr_version: 8.7.0 From 9b311c6d4a6e9fc3455be936c68099f9921ca715 Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 16:54:27 +0100 Subject: [PATCH 25/28] chore: testin --- .github/workflows/test_action.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index 2685e6e..2eb940a 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -26,5 +26,7 @@ jobs: root_options: -v --noop directory: ./pyproject commit: false - tag: true + push: false + changelog: false + vcs_release: false psr_version: 8.7.0 From 870d723503e98d75dc2f9775a06cd817f0fcb5c0 Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 17:04:15 +0100 Subject: [PATCH 26/28] test: try fetch depth 0 --- .github/workflows/test_action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test_action.yml b/.github/workflows/test_action.yml index 2eb940a..2685a54 100644 --- a/.github/workflows/test_action.yml +++ b/.github/workflows/test_action.yml @@ -18,6 +18,8 @@ jobs: path: ./action - uses: actions/checkout@v4 with: + token: ${{ secrets.PAT_TOKEN }} + fetch-depth: 0 repository: zckv/semantic-versioning-example path: ./pyproject - uses: ./action From 29295786f7c74bb565676c837fd1d6148f0fba1d Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 17:30:11 +0100 Subject: [PATCH 27/28] docs: add Readme --- README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ action.yml | 6 ++++-- 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ecbfba1 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# Python Semantic Release Composite Action +Composite action for PSR. +Official project is here: + https://github.com/python-semantic-release/python-semantic-release + +This action use PSR in the worker environment directly. +Python must be installed. + +You may use a specific version of PSR with this action. +For now, only versions 8 and 9 are supported. + +## Options + +| Name | Type | Description| +|---------------------------|------------|------------| +|`root_options` | string | Additional options for the main command. Example: -vv --noop| +|`directory` | string | Sub-directory to cd into before running semantic-release| +|`github_token` | string | GitHub token used to push release notes and new commits/tags| +|`git_committer_name` | string | The human name for the “committer” field| +|`git_committer_email` | string | The email address for the “committer” field| +|`ssh_public_signing_key` | string | The ssh public key used to sign commits| +|`ssh_private_signing_key` | string | The ssh private key used to sign commits| +|`prerelease` | boolean | Force the next version to be a prerelease. Set to "true" or "false".| +|`prerelease_token` | string | Force the next version to use this prerelease token, if it is a prerelease.| +|`force` | string | Force the next version to be a major release. Must be set to one of "prerelease", "patch", "minor", or "major". | +|`commit` | boolean | Whether or not to commit changes locally. Defaults are handled by python-semantic-release internal version command. | +|`tag` | boolean | Whether or not to make a local version tag. Defaults are handled by python-semantic-release internal version command.| +|`push` | boolean | Whether or not to push local commits to the Git repository. See the configuration page for defaults of `semantic-release version` for how the default is determined between push, tag, & commit.| +|`changelog` | boolean | Whether or not to update the changelog.| +|`vcs_release` | boolean | Whether or not to create a release in the remote VCS, if supported| +|`build` | boolean | Whether or not to run the build_command for the project. Defaults are handled by python-semantic-release internal version command.| +|`build_metadata` | string | Build metadata to append to the new version| +|`psr_version` | string | Pin python-semantic-release version to a specific value| + +### Example of use + +```yaml +jobs: + psr: + # Python is installed by default on github workers + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: ./action + with: + github_token: ${{ secrets.PAT_TOKEN }} + root_options: -v + prerelease: true + commit: true + push: true + vcs_release: false + psr_version: 8.7.0 +``` diff --git a/action.yml b/action.yml index fc7e817..19dfcc9 100644 --- a/action.yml +++ b/action.yml @@ -1,7 +1,10 @@ --- name: Python Semantic Release Composite Action -description: Automated Releases via SemVer and Commit Message Conventions +description: | + Automated Releases via SemVer and Commit Message Conventions. + Most of this file is copied from PSR official repository: + https://github.com/python-semantic-release/python-semantic-release branding: color: orange @@ -141,7 +144,6 @@ runs: INPUT_PSR_VERSION: ${{ inputs.psr_version }} run: | set -eux - env if ! command -v python $> /dev/null then echo "Python not found." From 2f4110e029d3d79ddf16119bd9ceff242d92b5b8 Mon Sep 17 00:00:00 2001 From: zckv Date: Wed, 15 Jan 2025 17:33:13 +0100 Subject: [PATCH 28/28] docs: correct action version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ecbfba1..bcde211 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: ./action + - uses: zckv/python-semantic-release-composite-action@v1 with: github_token: ${{ secrets.PAT_TOKEN }} root_options: -v