diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index bb0921032..85652f7c5 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -18,6 +18,19 @@ updates: rebase-strategy: auto versioning-strategy: "increase-if-necessary" + # Maintain dependencies for Docker (ie our GitHub Action) + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "monthly" + labels: + - dependencies + - dependabot + rebase-strategy: auto + commit-message: + prefix: "build" + include: "scope" # (deps) + - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/Dockerfile b/Dockerfile index 7396547e7..0ac58a764 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,29 @@ # This Dockerfile is only for GitHub Actions -FROM python:3.10-bullseye +FROM python:3.12-bookworm -RUN set -ex; \ - apt-get update; \ - apt-get install -y --no-install-recommends \ - git-lfs +# Copy python-semantic-release source code into container +COPY . /psr -# install backported stable version of git, which supports ssh signing -RUN echo "deb http://deb.debian.org/debian bullseye-backports main" >> /etc/apt/sources.list; \ - apt-get update;\ - apt-get install -y git/bullseye-backports +RUN \ + # Install desired packages + apt update && apt install -y --no-install-recommends \ + # install git with git-lfs support + git git-lfs \ + # install python cmodule / binary module build utilities + python3-dev gcc make cmake cargo \ + # Configure global pip + && { \ + printf '%s\n' "[global]"; \ + printf '%s\n' "no-cache-dir = true"; \ + printf '%s\n' "disable-pip-version-check = true"; \ + } > /etc/pip.conf \ + # Create virtual environment for python-semantic-release + && python3 -m venv /psr/.venv \ + # Update core utilities in the virtual environment + && /psr/.venv/bin/pip install -U pip setuptools wheel \ + # Install psr & its dependencies from source into virtual environment + && /psr/.venv/bin/pip install /psr \ + # Cleanup + && apt clean -y -ENV PYTHONPATH /semantic-release - -COPY . /semantic-release - -RUN cd /semantic-release && \ - python -m venv /semantic-release/.venv && \ - /semantic-release/.venv/bin/pip install . - -RUN /semantic-release/.venv/bin/python -m semantic_release --help - -ENTRYPOINT ["/semantic-release/action.sh"] +ENTRYPOINT ["/bin/bash", "-l", "/psr/action.sh"] diff --git a/action.sh b/action.sh old mode 100755 new mode 100644 index 3ec7c6624..1778f8119 --- a/action.sh +++ b/action.sh @@ -25,33 +25,19 @@ eval_boolean_action_input() { fi } -# Copy inputs into correctly-named environment variables -export GH_TOKEN="${INPUT_GITHUB_TOKEN}" -export PATH="${PATH}:/semantic-release/.venv/bin" -export GIT_COMMITTER_NAME="${INPUT_GIT_COMMITTER_NAME:="github-actions"}" -export GIT_COMMITTER_EMAIL="${INPUT_GIT_COMMITTER_EMAIL:="github-actions@github.com"}" -export SSH_PRIVATE_SIGNING_KEY="${INPUT_SSH_PRIVATE_SIGNING_KEY}" -export SSH_PUBLIC_SIGNING_KEY="${INPUT_SSH_PUBLIC_SIGNING_KEY}" -export GIT_COMMIT_AUTHOR="${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}>" -export ROOT_OPTIONS="${INPUT_ROOT_OPTIONS:="-v"}" -export PRERELEASE="${INPUT_PRERELEASE:="false"}" -export COMMIT="${INPUT_COMMIT:="false"}" -export PUSH="${INPUT_PUSH:="false"}" -export CHANGELOG="${INPUT_CHANGELOG:="false"}" -export VCS_RELEASE="${INPUT_VCS_RELEASE:="false"}" - # Convert inputs to command line arguments export ARGS=() -ARGS+=("$(eval_boolean_action_input "prerelease" "$PRERELEASE" "--prerelease" "")") || exit 1 -ARGS+=("$(eval_boolean_action_input "commit" "$COMMIT" "--commit" "--no-commit")") || exit 1 +# 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" "$PUSH" "--push" "--no-push")") || exit 1 -ARGS+=("$(eval_boolean_action_input "changelog" "$CHANGELOG" "--changelog" "--no-changelog")") || exit 1 -ARGS+=("$(eval_boolean_action_input "vcs_release" "$VCS_RELEASE" "--vcs-release" "--no-vcs-release")") || 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 # Handle --patch, --minor, --major # https://stackoverflow.com/a/47541882 -valid_force_levels=("patch" "minor" "major") +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 @@ -68,33 +54,51 @@ fi cd "${INPUT_DIRECTORY}" # Set Git details -git config --global user.name "$GIT_COMMITTER_NAME" -git config --global user.email "$GIT_COMMITTER_EMAIL" +if ! [ "${INPUT_GIT_COMMITTER_NAME:="-"}" = "-" ]; then + git config --global user.name "$INPUT_GIT_COMMITTER_NAME" +fi +if ! [ "${INPUT_GIT_COMMITTER_EMAIL:="-"}" = "-" ]; then + git config --global user.email "$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 $SSH_PUBLIC_SIGNING_KEY && -n $SSH_PRIVATE_SIGNING_KEY ]]; then +if [[ -n "$INPUT_SSH_PUBLIC_SIGNING_KEY" && -n "$INPUT_SSH_PRIVATE_SIGNING_KEY" ]]; then echo "SSH Key pair found, configuring signing..." - mkdir ~/.ssh - echo -e "$SSH_PRIVATE_SIGNING_KEY" >>~/.ssh/signing_key - cat ~/.ssh/signing_key - echo -e "$SSH_PUBLIC_SIGNING_KEY" >>~/.ssh/signing_key.pub + + # Write keys to disk + mkdir -vp ~/.ssh + echo -e "$INPUT_SSH_PUBLIC_SIGNING_KEY" >>~/.ssh/signing_key.pub cat ~/.ssh/signing_key.pub - chmod 600 ~/.ssh/signing_key && chmod 600 ~/.ssh/signing_key.pub - eval "$(ssh-agent)" + 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 --global gpg.format ssh + git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers git config --global user.signingKey ~/.ssh/signing_key git config --global commit.gpgsign true - git config --global user.email $GIT_COMMITTER_EMAIL - git config --global user.name $GIT_COMMITTER_NAME - touch ~/.ssh/allowed_signers - echo "$GIT_COMMITTER_EMAIL $SSH_PUBLIC_SIGNING_KEY" >~/.ssh/allowed_signers - git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers fi -# Run Semantic Release -/semantic-release/.venv/bin/python \ - -m semantic_release ${ROOT_OPTIONS} version ${ARGS[@]} +# Copy inputs into correctly-named environment variables +export GH_TOKEN="${INPUT_GITHUB_TOKEN}" + +# Run Semantic Release (explicitly use the GitHub action version) +eval "/psr/.venv/bin/semantic-release $INPUT_ROOT_OPTIONS version ${ARGS[*]}" diff --git a/action.yml b/action.yml index 481f14ae1..72bf011a6 100644 --- a/action.yml +++ b/action.yml @@ -8,24 +8,30 @@ inputs: description: "Additional options for the main command. Example: -vv --noop" required: false default: "-v" + directory: description: "Sub-directory to cd into before running semantic-release" default: "." required: false + github_token: description: "GitHub token used to push release notes and new commits/tags" required: true + git_committer_name: description: "The human name for the “committer” field" default: "github-actions" required: false + git_committer_email: description: "The email address for the “committer” field" default: "github-actions@github.com" required: false + ssh_public_signing_key: description: "The ssh public key used to sign commits" required: false + ssh_private_signing_key: description: "The ssh private key used to sign commits" required: false @@ -36,7 +42,6 @@ inputs: required: false description: | Force the next version to be a prerelease. Set to "true" or "false". - default: "false" prerelease_token: type: string @@ -48,13 +53,13 @@ inputs: required: false description: | Force the next version to be a major release. Must be set to - one of "patch", "minor", or "major". + one of "prerelease", "patch", "minor", or "major". commit: type: string required: false - default: "true" - description: Whether or not to commit changes locally + description: Whether or not to commit changes locally. Defaults are handled + by python-semantic-release internal version command. tag: type: string @@ -66,24 +71,20 @@ inputs: push: type: string required: false - default: "true" description: | - Whether or not to push local commits to the Git repository. - Defaults to "true", but when either the "commit" or "tag" - input is "false", this push setting will also be set to - "false" regardless of the value supplied. + 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 - default: "true" description: | Whether or not to update the changelog. vcs_release: type: string required: false - default: "true" description: | Whether or not to create a release in the remote VCS, if supported diff --git a/docs/github-action.rst b/docs/github-action.rst index 7129ede28..ae3a4e23e 100644 --- a/docs/github-action.rst +++ b/docs/github-action.rst @@ -106,8 +106,8 @@ defaults as their corresponding command line option. In general, the input for an action corresponding to a command line option has the same name, with dashes (``-``) replaced by underscores. -The command line arguments ``--patch``, ``--minor`` and ``--major`` are mutually -exclusive, and are supplied via the ``force`` input. +The command line arguments ``--prerelease``, ``--patch``, ``--minor`` and ``--major`` +are mutually exclusive, and are supplied via the ``force`` input. Flags, which require either ``--