Skip to content

Commit

Permalink
refactor: optimize & improve maintainability of GitHub Action definit…
Browse files Browse the repository at this point in the history
…ion (#914)

* fix(gha): correct use of `prerelease` option for GitHub Action

* style(gha): improve shell format of GitHub Action script

* docs(gha): update GitHub Actions doc with all available options

* refactor(gha): drop cli defaults from action definition

* refactor(gha): optimize gha docker definition

* refactor(gha): drop defaults & optimize action entrypoint script

* chore(dependabot): add updater for gha docker environment

* refactor(gha): execute the gha version of semantic-release

* refactor(gha): update container os to bookworm, dropping backports need

  When using Debian Bullseye, it did not have a git version available
  that supported SSH key signing. SSH key signing was integrated in
  git version 2.34 and the highest version for Bullseye was 2.30. Through
  the backports repository, a version greater than 2.34 was made available
  but now bumping to Debian Bookworm, the available version is 2.39 in the
  base OS repository so no backports configuration required.

* build(deps): bump GitHub Action container to use `python3.12`

  Updates the base container that runs the GitHub Action environment to
  python3.12 which enables users to specify and run build scripts that
  are python3.12 specific as python3.12 is now the latest stable version
  of python available and we were only providing `3.10`.

  Resolves: #801

* refactor(gha): add common python binary module deps for builds

* refactor(gha): removed execute permissions on action script
  • Loading branch information
codejedi365 committed May 6, 2024
1 parent 6b24288 commit 85e27b7
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 71 deletions.
13 changes: 13 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
45 changes: 25 additions & 20 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -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"]
80 changes: 42 additions & 38 deletions action.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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[*]}"
23 changes: 12 additions & 11 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
7 changes: 5 additions & 2 deletions docs/github-action.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,18 @@ 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 ``--<option>`` or ``--no-<option>`` to be passed on the
command-line, should be specified using the option name (with dashes replaced by
underscores), and set to the value ``"true"`` to supply ``--<option>`` on the
command-line, and ``"false"`` to specify ``--no-<option>``.
Any other values are not accepted.

The flag ``--as-prerelease`` is uniquely provided as just the ``prerelease`` flag value.
This is for compatibility reasons.

For command line options requiring a value, set the input to the required value.

For example, to specify ``--patch --no-push --build-metadata abc123``, you should
Expand Down

0 comments on commit 85e27b7

Please sign in to comment.