Skip to content

Commit ee0a47c

Browse files
committed
test: add test suite for runtime evaluation of Docker Action container
1 parent f1332e4 commit ee0a47c

File tree

8 files changed

+305
-1
lines changed

8 files changed

+305
-1
lines changed

CONTRIBUTING.rst

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
11
Contributing
2-
------------
2+
============
33

44
If you want to contribute that is awesome. Remember to be nice to others in issues and reviews.
55

66
Unsure about something? No worries, `ask a question`__.
77

88
__ https://github.com/python-semantic-release/publish-action/issues/new
9+
10+
Development Notes
11+
=================
12+
13+
Building the Action Environment
14+
-------------------------------
15+
16+
.. code:: bash
17+
18+
docker build -t psr-publish-action:latest .
19+
20+
Local Testing
21+
-------------
22+
23+
To test make sure to first build the action container with the appropriate tag. Then
24+
run the tests with the following command:
25+
26+
.. code:: bash
27+
28+
TEST_CONTAINER_TAG="psr-publish-action:latest" bash tests/run.sh
29+
30+
.. note::
31+
The tests will clean up after themselves with the ``--rm`` flag for the container
32+
run command and will automatically remove the test project directory on completion.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ZmFrZSBleGFtcGxlIHdoZWVsCg==
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[project]
2+
name = "example"
3+
version = "0.0.0"
4+
description = "Example project"

tests/example_project/releaserc.toml

Whitespace-only changes.

tests/run.sh

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# TODO: REmove --- temporary
6+
realpath() {
7+
readlink -f "$1"
8+
}
9+
10+
PROJ_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")/..")"
11+
EXAMPLE_PROJECT_BASE_DIR="${EXAMPLE_PROJECT_BASE_DIR:-"$PROJ_DIR/tests/example_project"}"
12+
13+
if [ -z "${UTILS_LOADED}" ]; then
14+
# shellcheck source=tests/utils.sh
15+
source "$PROJ_DIR/tests/utils.sh"
16+
fi
17+
18+
create_example_project() {
19+
local EXAMPLE_PROJECT_DIR="$1"
20+
21+
log "Creating example project in: $EXAMPLE_PROJECT_DIR"
22+
mkdir -vp "$(dirname "$EXAMPLE_PROJECT_DIR")"
23+
cp -r "${EXAMPLE_PROJECT_BASE_DIR}" "$EXAMPLE_PROJECT_DIR"
24+
25+
pushd "$EXAMPLE_PROJECT_DIR" >/dev/null || return 1
26+
log "Constructing git history in repository"
27+
git init
28+
git add .
29+
git commit -m "Initial commit"
30+
git remote add origin "https://github.com/python-semantic-release/example-project.git"
31+
32+
cat <<EOF >pyproject.toml
33+
[project]
34+
name = "example"
35+
version = "1.0.0"
36+
description = "Example project"
37+
EOF
38+
git commit -am '1.0.0'
39+
git tag -a v1.0.0 -m "v1.0.0"
40+
41+
popd >/dev/null || return 1
42+
log "Example project created successfully"
43+
}
44+
45+
# ------------------------------
46+
# TEST SUITE DRIVER
47+
# ------------------------------
48+
49+
run_test_suite() {
50+
local ALL_TEST_FNS
51+
52+
# Dynamically import all test scripts
53+
for test_script in "$PROJ_DIR"/tests/suite/test_*.sh; do
54+
if [ -f "$test_script" ]; then
55+
if ! source "$test_script"; then
56+
error "Failed to load test script: $test_script"
57+
fi
58+
fi
59+
done
60+
61+
# Extract all test functions
62+
tests_in_env="$(compgen -A function | grep "^test_")"
63+
read -r -a ALL_TEST_FNS <<< "$(printf '%s' "$tests_in_env" | tr '\n' ' ')"
64+
65+
log ""
66+
log "************************"
67+
log "* Running test suite *"
68+
log "************************"
69+
70+
# Incrementally run all test functions and flag if any fail
71+
local test_index=1
72+
local test_failures=0
73+
for test_fn in "${ALL_TEST_FNS[@]}"; do
74+
if command -v "$test_fn" &>/dev/null; then
75+
if ! "$test_fn" "$test_index"; then
76+
((test_failures++))
77+
fi
78+
fi
79+
log "--------------------------------------------------------------------------------"
80+
((test_index++))
81+
done
82+
83+
log ""
84+
log "************************"
85+
log "* Test Summary *"
86+
log "************************"
87+
log ""
88+
log "Total tests executed: ${#ALL_TEST_FNS[@]}"
89+
log "Successes: $((${#ALL_TEST_FNS[@]} - test_failures))"
90+
log "Failures: $test_failures"
91+
92+
if [ "$test_failures" -gt 0 ]; then
93+
return 1
94+
fi
95+
}
96+
97+
# ------------------------------
98+
# MAIN
99+
# ------------------------------
100+
101+
log "================================================================================"
102+
log "|| Publish Action Test Runner ||"
103+
log "================================================================================"
104+
log "Initializing..."
105+
106+
# Make absolute path to project directory
107+
PROJECT_MOUNT_DIR="${PROJ_DIR:?}/${PROJECT_MOUNT_DIR:?}"
108+
109+
log ""
110+
log "******************************"
111+
log "* Running test suite setup *"
112+
log "******************************"
113+
log ""
114+
115+
# Setup project environment
116+
create_example_project "$PROJECT_MOUNT_DIR"
117+
trap 'rm -rf "${PROJECT_MOUNT_DIR:?}"' EXIT
118+
119+
run_test_suite

tests/suite/test_publish_w_tag.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/bin/bash
2+
3+
__file__="$(realpath "${BASH_SOURCE[0]}")"
4+
__directory__="$(dirname "${__file__}")"
5+
6+
if ! [ "${UTILS_LOADED}" = "true" ]; then
7+
# shellcheck source=tests/utils.sh
8+
source "$__directory__/../utils.sh"
9+
fi
10+
11+
test_with_tag() {
12+
# Using default configuration within PSR with no modifications
13+
# triggering the NOOP mode to prevent errors since the repo doesn't exist
14+
# We are just trying to test that the root options & tag arguments are
15+
# passed to the action without a fatal error
16+
local index="${1:?Index not provided}"
17+
local test_name="Test with tag"
18+
19+
# Create expectations & set env variables that will be passed in for Docker command
20+
local WITH_VAR_GITHUB_TOKEN="ghp_1x2x3x4x5x6x7x8x9x0x1x2x3x4x5x6x7x8x9x0"
21+
local WITH_VAR_TAG="v1.0.0"
22+
local WITH_VAR_ROOT_OPTIONS="--noop -vv"
23+
local expected_psr_cmd=".*/bin/semantic-release $WITH_VAR_ROOT_OPTIONS publish --tag $WITH_VAR_TAG"
24+
25+
# Execute the test & capture output
26+
# Fatal errors if exit code is not 0
27+
local output=""
28+
if ! output="$(run_test "$index. $test_name" 2>&1)"; then
29+
# Log the output for debugging purposes
30+
log "$output"
31+
error "fatal error occurred!"
32+
error "::error:: $test_name failed!"
33+
return 1
34+
fi
35+
36+
# Evaluate the output to ensure the expected command is present
37+
if ! printf '%s' "$output" | grep -q "$expected_psr_cmd"; then
38+
# Log the output for debugging purposes
39+
log "$output"
40+
error "Failed to find the expected command in the output!"
41+
error "\tExpected Command: $expected_psr_cmd"
42+
error "::error:: $test_name failed!"
43+
return 1
44+
fi
45+
46+
log "\n$index. $test_name: PASSED!"
47+
}

tests/suite/test_publish_wo_tag.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
3+
__file__="$(realpath "${BASH_SOURCE[0]}")"
4+
__directory__="$(dirname "${__file__}")"
5+
6+
if ! [ "${UTILS_LOADED}" = "true" ]; then
7+
# shellcheck source=tests/utils.sh
8+
source "$__directory__/../utils.sh"
9+
fi
10+
11+
test_without_tag() {
12+
# Using default configuration within PSR with no modifications
13+
# triggering the NOOP mode to prevent errors since the repo doesn't exist
14+
# We are just trying to test that the root options are passed to the action
15+
# without a fatal error
16+
local index="${1:?Index not provided}"
17+
local test_name="Test without tag"
18+
19+
# Create expectations & set env variables that will be passed in for Docker command
20+
local WITH_VAR_GITHUB_TOKEN="ghp_1x2x3x4x5x6x7x8x9x0x1x2x3x4x5x6x7x8x9x0"
21+
local WITH_VAR_ROOT_OPTIONS="--noop -vv"
22+
local expected_psr_cmd=".*/bin/semantic-release $WITH_VAR_ROOT_OPTIONS publish"
23+
24+
# Execute the test & capture output
25+
# Fatal errors if exit code is not 0
26+
local output=""
27+
if ! output="$(run_test "$index. $test_name" 2>&1)"; then
28+
# Log the output for debugging purposes
29+
log "$output"
30+
error "fatal error occurred!"
31+
error "::error:: $test_name failed!"
32+
return 1
33+
fi
34+
35+
# Evaluate the output to ensure the expected command is present
36+
if ! printf '%s' "$output" | grep -q "$expected_psr_cmd"; then
37+
# Log the output for debugging purposes
38+
log "$output"
39+
error "Failed to find the expected command in the output!"
40+
error "\tExpected Command: $expected_psr_cmd"
41+
error "::error:: $test_name failed!"
42+
return 1
43+
fi
44+
45+
log "\n$index. $test_name: PASSED!"
46+
}

tests/utils.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/bash
2+
3+
# ------------------------------
4+
# UTILS
5+
# ------------------------------
6+
IMAGE_TAG="${TEST_CONTAINER_TAG:?TEST_CONTAINER_TAG not set}"
7+
PROJECT_MOUNT_DIR="${PROJECT_MOUNT_DIR:-"tmp/project"}"
8+
GITHUB_ACTIONS_CWD="/github/workspace"
9+
10+
log() {
11+
printf '%b\n' "$*"
12+
}
13+
14+
error() {
15+
log >&2 "\033[31m$*\033[0m"
16+
}
17+
18+
explicit_run_cmd() {
19+
local cmd="$*"
20+
log "$> $cmd\n"
21+
eval "$cmd"
22+
}
23+
24+
run_test() {
25+
local test_name="$1"
26+
27+
# Set Defaults based on action.yml
28+
[ -z "$WITH_VAR_DIRECTORY" ] && local WITH_VAR_DIRECTORY="."
29+
[ -z "$WITH_VAR_ROOT_OPTIONS" ] && local WITH_VAR_ROOT_OPTIONS="-v"
30+
31+
# Extract all WITH_VAR_ variables dynamically from environment
32+
local ENV_ARGS=()
33+
args_in_env="$(compgen -A variable | grep "^WITH_VAR_")"
34+
read -r -a ENV_ARGS <<< "$(printf '%s' "$args_in_env" | tr '\n' ' ')"
35+
36+
# Set Docker arguments (default: always remove the container after execution)
37+
local DOCKER_ARGS=("--rm")
38+
39+
# Add all WITH_VAR_ variables to the Docker command
40+
local actions_input_var_name=""
41+
for input in "${ENV_ARGS[@]}"; do
42+
# Convert WITH_VAR_ to INPUT_ to simulate GitHub Actions input syntax
43+
actions_input_var_name="INPUT_${input#WITH_VAR_}"
44+
45+
# Add the environment variable to the Docker command
46+
DOCKER_ARGS+=("-e ${actions_input_var_name}='${!input}'")
47+
done
48+
49+
# Add the project directory to the Docker command
50+
DOCKER_ARGS+=("-v ${PROJECT_MOUNT_DIR}:${GITHUB_ACTIONS_CWD}")
51+
52+
# Set the working directory to the project directory
53+
DOCKER_ARGS+=("-w ${GITHUB_ACTIONS_CWD}")
54+
55+
# Run the test
56+
log "\n$test_name"
57+
log "--------------------------------------------------------------------------------"
58+
if ! explicit_run_cmd "docker run ${DOCKER_ARGS[*]} $IMAGE_TAG"; then
59+
return 1
60+
fi
61+
}
62+
63+
export UTILS_LOADED="true"

0 commit comments

Comments
 (0)