From 1bdbfe4398959dec1c83eefecb9b3469f333538c Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 8 Sep 2026 16:58:53 -0400 Subject: [PATCH 1/3] Reuse existing WordPress upgrade pull request --- .github/workflows/test.yml | 2 + README.md | 6 ++ check-upgrade.sh | 79 ++++++++++++--- tests/check-upgrade.sh | 202 +++++++++++++++++++++++++++++++++++++ tests/stubs/curl | 3 + tests/stubs/date | 3 + tests/stubs/gh | 19 ++++ tests/stubs/git | 11 ++ tests/stubs/sed | 4 + tests/stubs/sort | 7 ++ 10 files changed, 320 insertions(+), 16 deletions(-) create mode 100755 tests/check-upgrade.sh create mode 100755 tests/stubs/curl create mode 100755 tests/stubs/date create mode 100755 tests/stubs/gh create mode 100755 tests/stubs/git create mode 100755 tests/stubs/sed create mode 100755 tests/stubs/sort diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7860e69..52a2e3f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,3 +17,5 @@ jobs: uses: actions/checkout@v3 - name: Shellcheck uses: ludeeus/action-shellcheck@master + - name: Behavior tests + run: ./tests/check-upgrade.sh diff --git a/README.md b/README.md index 51ebe10..ec350ca 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,12 @@ jobs: The action assumes that a `package-lock.json` file exists in the root of the repository to run `npm ci`. +When one or more open pull requests created by this action already exist, the +action updates the newest pull request's branch, title, and checklist instead +of opening another pull request. It also comments on the pull request with the +previous and new WordPress versions. Closed and merged pull requests are not +reused. + ### Inputs - `plugin-file` - The name of the plugin's main file. Defaults to `plugin.php`. diff --git a/check-upgrade.sh b/check-upgrade.sh index 4b23f5c..6ce5609 100755 --- a/check-upgrade.sh +++ b/check-upgrade.sh @@ -1,7 +1,26 @@ #!/bin/bash +set -o pipefail + # Automatically upgrade a plugin to match the latest WordPress version. +function normalize_version() { + echo "$1" | awk -F. '{printf("%d.%d.%d\n", $1,$2,$3)}' +} + +function update_pull_request() { + local comment_marker="" + local comments + local update_note="Updated this pull request from WordPress \`$PREVIOUS_VERSION\` to \`$WP_VERSION\` instead of opening a new pull request. $comment_marker" + + gh pr edit "$PR_NUMBER" --title "Upgrade plugin to WordPress $WP_VERSION" --body "- [ ] Test plugin against WordPress \`$WP_VERSION\`" + comments=$(gh api --paginate "repos/{owner}/{repo}/issues/$PR_NUMBER/comments" --jq '.[].body') + + if ! grep -Fq "$comment_marker" <<< "$comments"; then + gh pr comment "$PR_NUMBER" --body "$update_note" + fi +} + # Ensure PLUGIN_FILE is set. if [ -z "$PLUGIN_FILE" ]; then echo "[action-update-wordpress-plugin] PLUGIN_FILE is not set." @@ -18,7 +37,7 @@ fi LATEST_VERSION=$(grep "Tested up to:" "$PLUGIN_FILE" | awk '{print $NF}') # Ensure latest version is always in x.x.x format (e.g. 5.2.1 vs 5.2). -LATEST_VERSION=$(echo "$LATEST_VERSION" | awk -F. '{printf("%d.%d.%d\n", $1,$2,$3)}') +LATEST_VERSION=$(normalize_version "$LATEST_VERSION") # Check if the latest version is set and not empty. if [ -z "$LATEST_VERSION" ]; then @@ -28,9 +47,10 @@ fi # Fetch the latest WordPress version from api.wordpress.org. WP_VERSION=$(curl -s https://api.wordpress.org/core/version-check/1.7/ | jq -r '.offers[0].version') +WP_NORMALIZED_VERSION=$(normalize_version "$WP_VERSION") -# Early exist if they're the same version. -if [ "$WP_VERSION" == "$LATEST_VERSION" ]; then +# Early exit if they're the same version. +if [ "$WP_NORMALIZED_VERSION" == "$LATEST_VERSION" ]; then echo "[action-update-wordpress-plugin] Latest WordPress version and plugin-supported version are the same, no upgrade needed." exit 0 fi @@ -43,26 +63,49 @@ function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; } -if version_gt "$LATEST_VERSION" "$WP_VERSION"; then +if version_gt "$LATEST_VERSION" "$WP_NORMALIZED_VERSION"; then echo "[action-update-wordpress-plugin] Latest WordPress version is greater than the latest plugin supported version, no upgrade needed." exit 0 else echo "[action-update-wordpress-plugin] Latest WordPress version is less than the latest plugin supported version, upgrade needed." fi -# Check if a pull request already exists with the gh cli. -if [ "$(gh pr list --search "Upgrade plugin to WordPress $WP_VERSION" --state "all" | wc -l)" -gt 0 ]; then - echo "[action-update-wordpress-plugin] Pull request already exists, no upgrade needed." - exit 0 -fi - echo "[action-update-wordpress-plugin] Upgrading plugin to $WP_VERSION ..." set -e -# Checkout a new branch including the current time -BRANCH_NAME="action/upgrade-to-$WP_VERSION-$(date +%s)" -git checkout -b "$BRANCH_NAME" +OPEN_PR=$(gh pr list --app github-actions --state open --limit 1000 --json number,headRefName,title,isCrossRepository | jq -r 'sort_by(.number) | reverse | map(select(.isCrossRepository == false and (.headRefName | startswith("action/upgrade-to-")))) | first | if . then [.number, .headRefName, .title] | @tsv else empty end') + +if [ -n "$OPEN_PR" ]; then + IFS=$'\t' read -r PR_NUMBER BRANCH_NAME PR_TITLE <<< "$OPEN_PR" + echo "[action-update-wordpress-plugin] Reusing pull request #$PR_NUMBER: $PR_TITLE" + git fetch origin "$BRANCH_NAME" + git checkout -B "$BRANCH_NAME" "origin/$BRANCH_NAME" + + PREVIOUS_VERSION=$(grep "Tested up to:" "$PLUGIN_FILE" | awk '{print $NF}') + PREVIOUS_VERSION=$(normalize_version "$PREVIOUS_VERSION") + + if [ "$WP_NORMALIZED_VERSION" == "$PREVIOUS_VERSION" ]; then + BRANCH_VERSION=${BRANCH_NAME#action/upgrade-to-} + BRANCH_VERSION=$(normalize_version "${BRANCH_VERSION%-*}") + + if [ "$BRANCH_VERSION" != "$WP_NORMALIZED_VERSION" ]; then + PREVIOUS_VERSION=$(git show HEAD^:"${PLUGIN_FILE#./}" 2>/dev/null | grep "Tested up to:" | awk '{print $NF}') + PREVIOUS_VERSION=$(normalize_version "${PREVIOUS_VERSION:-$BRANCH_VERSION}") + update_pull_request + echo "[action-update-wordpress-plugin] Pull request #$PR_NUMBER metadata updated" + else + echo "[action-update-wordpress-plugin] Pull request #$PR_NUMBER already targets WordPress $WP_VERSION, no update needed." + fi + + exit 0 + fi +else + PR_NUMBER="" + PREVIOUS_VERSION="$LATEST_VERSION" + BRANCH_NAME="action/upgrade-to-$WP_VERSION-$(date +%s)" + git checkout -b "$BRANCH_NAME" +fi # npm ci if UPGRADE_DEPENDENCIES is not equal to "false". if [ "$UPGRADE_DEPENDENCIES" != "false" ]; then @@ -90,8 +133,12 @@ git config --global user.name "$GITHUB_ACTOR" git add -A && git commit -m "Upgrade plugin to $WP_VERSION" git push origin "$BRANCH_NAME" -# Create a pull request. -gh pr create --title "Upgrade plugin to WordPress $WP_VERSION" --body "- [ ] Test plugin against WordPress \`$WP_VERSION\`" --head "$BRANCH_NAME" +if [ -n "$PR_NUMBER" ]; then + update_pull_request + echo "[action-update-wordpress-plugin] Pull request #$PR_NUMBER updated" +else + gh pr create --title "Upgrade plugin to WordPress $WP_VERSION" --body "- [ ] Test plugin against WordPress \`$WP_VERSION\`" --head "$BRANCH_NAME" + echo "[action-update-wordpress-plugin] Pull request created" +fi -echo "[action-update-wordpress-plugin] Pull request created" exit 0 diff --git a/tests/check-upgrade.sh b/tests/check-upgrade.sh new file mode 100755 index 0000000..97183d9 --- /dev/null +++ b/tests/check-upgrade.sh @@ -0,0 +1,202 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) + +fail() { + echo "not ok - $1" + exit 1 +} + +assert_contains() { + local file=$1 + local expected=$2 + + grep -Fq -- "$expected" "$file" || fail "Expected $file to contain: $expected" +} + +assert_not_contains() { + local file=$1 + local unexpected=$2 + + if grep -Fq -- "$unexpected" "$file"; then + fail "Expected $file not to contain: $unexpected" + fi +} + +setup_case() { + TEST_DIR=$(mktemp -d) + export TEST_DIR + export COMMAND_LOG="$TEST_DIR/commands.log" + export PLUGIN_FILE="$TEST_DIR/plugin.php" + export UPGRADE_DEPENDENCIES=false + export GITHUB_ACTOR=github-actions + export GH_PR_LIST_OUTPUT=${1:-[]} + unset CHECKOUT_PLUGIN_VERSION GH_API_FAIL GH_PR_COMMENTS_OUTPUT GH_PR_LIST_FAIL PARENT_PLUGIN_VERSION WORDPRESS_VERSION + + printf '%s\n' ' "$PLUGIN_FILE" + : > "$COMMAND_LOG" + mkdir "$TEST_DIR/bin" + + for command in curl date gh git sed sort; do + ln -s "$ROOT_DIR/tests/stubs/$command" "$TEST_DIR/bin/$command" + done + + export PATH="$TEST_DIR/bin:$PATH" +} + +teardown_case() { + rm -rf "$TEST_DIR" +} + +test_updates_existing_pull_request() { + setup_case '[{"number":42,"headRefName":"action/upgrade-to-6.7.0-1700000000","title":"Upgrade plugin to WordPress 6.7.0","isCrossRepository":false}]' + + "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" + + assert_contains "$COMMAND_LOG" "gh pr list --app github-actions --state open --limit 1000 --json number,headRefName,title,isCrossRepository" + assert_contains "$COMMAND_LOG" "git fetch origin action/upgrade-to-6.7.0-1700000000" + assert_contains "$COMMAND_LOG" "git checkout -B action/upgrade-to-6.7.0-1700000000 origin/action/upgrade-to-6.7.0-1700000000" + assert_contains "$COMMAND_LOG" "git push origin action/upgrade-to-6.7.0-1700000000" + assert_contains "$COMMAND_LOG" "gh pr edit 42 --title Upgrade plugin to WordPress 6.8.0" + assert_contains "$COMMAND_LOG" 'gh pr comment 42 --body Updated this pull request from WordPress `6.7.0` to `6.8.0` instead of opening a new pull request. ' + assert_not_contains "$COMMAND_LOG" "gh pr create" + + teardown_case + echo "ok - updates an existing pull request" +} + +test_skips_existing_pull_request_at_current_version() { + setup_case '[{"number":42,"headRefName":"action/upgrade-to-6.8.0-1700000000","title":"Upgrade plugin to WordPress 6.8.0","isCrossRepository":false}]' + export CHECKOUT_PLUGIN_VERSION=6.8.0 + + "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" + + assert_contains "$TEST_DIR/output.log" "Pull request #42 already targets WordPress 6.8.0, no update needed." + assert_not_contains "$COMMAND_LOG" "git commit" + assert_not_contains "$COMMAND_LOG" "git push" + assert_not_contains "$COMMAND_LOG" "gh pr edit" + assert_not_contains "$COMMAND_LOG" "gh pr comment" + + unset CHECKOUT_PLUGIN_VERSION + teardown_case + echo "ok - skips an existing pull request at the current version" +} + +test_creates_pull_request_when_none_exists() { + setup_case + + "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" + + assert_contains "$COMMAND_LOG" "git checkout -b action/upgrade-to-6.8.0-1700000000" + assert_contains "$COMMAND_LOG" "git push origin action/upgrade-to-6.8.0-1700000000" + assert_contains "$COMMAND_LOG" "gh pr create --title Upgrade plugin to WordPress 6.8.0" + assert_not_contains "$COMMAND_LOG" "gh pr edit" + assert_not_contains "$COMMAND_LOG" "gh pr comment" + + teardown_case + echo "ok - creates a pull request when none exists" +} + +test_treats_equivalent_version_formats_as_current() { + setup_case '[{"number":42,"headRefName":"action/upgrade-to-6.8-1700000000","title":"Upgrade plugin to WordPress 6.8","isCrossRepository":false}]' + export CHECKOUT_PLUGIN_VERSION=6.8.0 + export WORDPRESS_VERSION=6.8 + + "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" + + assert_contains "$TEST_DIR/output.log" "Pull request #42 already targets WordPress 6.8, no update needed." + assert_not_contains "$COMMAND_LOG" "git commit" + assert_not_contains "$COMMAND_LOG" "git push" + + unset CHECKOUT_PLUGIN_VERSION WORDPRESS_VERSION + teardown_case + echo "ok - treats equivalent version formats as current" +} + +test_repairs_pull_request_metadata_after_push_succeeds() { + setup_case '[{"number":42,"headRefName":"action/upgrade-to-6.7.0-1700000000","title":"Upgrade plugin to WordPress 6.7.0","isCrossRepository":false}]' + export CHECKOUT_PLUGIN_VERSION=6.8.0 + export PARENT_PLUGIN_VERSION=6.7.0 + + "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" + + assert_contains "$COMMAND_LOG" "gh pr edit 42 --title Upgrade plugin to WordPress 6.8.0" + assert_contains "$COMMAND_LOG" 'gh pr comment 42 --body Updated this pull request from WordPress `6.7.0` to `6.8.0` instead of opening a new pull request. ' + assert_not_contains "$COMMAND_LOG" "git commit" + assert_not_contains "$COMMAND_LOG" "git push" + + unset CHECKOUT_PLUGIN_VERSION PARENT_PLUGIN_VERSION + teardown_case + echo "ok - repairs pull request metadata after push succeeds" +} + +test_does_not_duplicate_update_note_on_retry() { + setup_case '[{"number":42,"headRefName":"action/upgrade-to-6.7.0-1700000000","title":"Upgrade plugin to WordPress 6.8.0","isCrossRepository":false}]' + export CHECKOUT_PLUGIN_VERSION=6.8.0 + export PARENT_PLUGIN_VERSION=6.7.0 + export GH_PR_COMMENTS_OUTPUT='Updated previously. ' + + "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" + + assert_contains "$COMMAND_LOG" "gh pr edit 42 --title Upgrade plugin to WordPress 6.8.0" + assert_not_contains "$COMMAND_LOG" "gh pr comment" + + unset CHECKOUT_PLUGIN_VERSION PARENT_PLUGIN_VERSION GH_PR_COMMENTS_OUTPUT + teardown_case + echo "ok - does not duplicate the update note on retry" +} + +test_selects_newest_same_repository_action_pull_request() { + setup_case '[{"number":45,"headRefName":"action/upgrade-to-6.7.0-4","title":"Fork","isCrossRepository":true},{"number":44,"headRefName":"unrelated","title":"Unrelated","isCrossRepository":false},{"number":42,"headRefName":"action/upgrade-to-6.7.0-2","title":"Newest match","isCrossRepository":false},{"number":41,"headRefName":"action/upgrade-to-6.7.0-1","title":"Older match","isCrossRepository":false}]' + + "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" + + assert_contains "$COMMAND_LOG" "git fetch origin action/upgrade-to-6.7.0-2" + assert_contains "$COMMAND_LOG" "gh pr edit 42" + assert_not_contains "$COMMAND_LOG" "git fetch origin action/upgrade-to-6.7.0-4" + assert_not_contains "$COMMAND_LOG" "gh pr edit 45" + + teardown_case + echo "ok - selects the newest same-repository action pull request" +} + +test_stops_when_pull_request_lookup_fails() { + setup_case + export GH_PR_LIST_FAIL=true + + if "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" 2>&1; then + fail "Expected pull request lookup failure to stop the action" + fi + + assert_not_contains "$COMMAND_LOG" "git checkout -b" + assert_not_contains "$COMMAND_LOG" "gh pr create" + + teardown_case + echo "ok - stops when pull request lookup fails" +} + +test_stops_when_comment_lookup_fails() { + setup_case '[{"number":42,"headRefName":"action/upgrade-to-6.7.0-1700000000","title":"Upgrade plugin to WordPress 6.7.0","isCrossRepository":false}]' + export GH_API_FAIL=true + + if "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" 2>&1; then + fail "Expected comment lookup failure to stop the action" + fi + + assert_not_contains "$COMMAND_LOG" "gh pr comment" + + teardown_case + echo "ok - stops when comment lookup fails" +} + +test_updates_existing_pull_request +test_skips_existing_pull_request_at_current_version +test_creates_pull_request_when_none_exists +test_treats_equivalent_version_formats_as_current +test_repairs_pull_request_metadata_after_push_succeeds +test_does_not_duplicate_update_note_on_retry +test_selects_newest_same_repository_action_pull_request +test_stops_when_pull_request_lookup_fails +test_stops_when_comment_lookup_fails diff --git a/tests/stubs/curl b/tests/stubs/curl new file mode 100755 index 0000000..86f6419 --- /dev/null +++ b/tests/stubs/curl @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +printf '{"offers":[{"version":"%s"}]}\n' "${WORDPRESS_VERSION:-6.8.0}" diff --git a/tests/stubs/date b/tests/stubs/date new file mode 100755 index 0000000..1cc6490 --- /dev/null +++ b/tests/stubs/date @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +echo '1700000000' diff --git a/tests/stubs/gh b/tests/stubs/gh new file mode 100755 index 0000000..11e8e50 --- /dev/null +++ b/tests/stubs/gh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +printf 'gh %s\n' "$*" >> "$COMMAND_LOG" + +if [ "$1 $2" = "pr list" ]; then + if [ "${GH_PR_LIST_FAIL-}" = "true" ]; then + exit 1 + fi + + printf '%s\n' "$GH_PR_LIST_OUTPUT" +fi + +if [ "$1" = "api" ]; then + if [ "${GH_API_FAIL-}" = "true" ]; then + exit 1 + fi + + printf '%s\n' "${GH_PR_COMMENTS_OUTPUT-}" +fi diff --git a/tests/stubs/git b/tests/stubs/git new file mode 100755 index 0000000..dfd90a2 --- /dev/null +++ b/tests/stubs/git @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +printf 'git %s\n' "$*" >> "$COMMAND_LOG" + +if [ "$1" = "checkout" ] && [ -n "${CHECKOUT_PLUGIN_VERSION-}" ]; then + printf '%s\n' ' "$PLUGIN_FILE" +fi + +if [ "$1" = "show" ] && [ -n "${PARENT_PLUGIN_VERSION-}" ]; then + printf '%s\n' ' "$3.tmp" +mv "$3.tmp" "$3" diff --git a/tests/stubs/sort b/tests/stubs/sort new file mode 100755 index 0000000..55061e1 --- /dev/null +++ b/tests/stubs/sort @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +if [ "${1-}" = "-V" ]; then + shift +fi + +/usr/bin/sort "$@" From c95a3496295df4fabe5f1f19a0bfab84ad3a4ea6 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 8 Sep 2026 17:38:23 -0400 Subject: [PATCH 2/3] Fix ShellCheck warnings in behavior tests --- tests/check-upgrade.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/check-upgrade.sh b/tests/check-upgrade.sh index 97183d9..886f9ff 100755 --- a/tests/check-upgrade.sh +++ b/tests/check-upgrade.sh @@ -60,7 +60,7 @@ test_updates_existing_pull_request() { assert_contains "$COMMAND_LOG" "git checkout -B action/upgrade-to-6.7.0-1700000000 origin/action/upgrade-to-6.7.0-1700000000" assert_contains "$COMMAND_LOG" "git push origin action/upgrade-to-6.7.0-1700000000" assert_contains "$COMMAND_LOG" "gh pr edit 42 --title Upgrade plugin to WordPress 6.8.0" - assert_contains "$COMMAND_LOG" 'gh pr comment 42 --body Updated this pull request from WordPress `6.7.0` to `6.8.0` instead of opening a new pull request. ' + assert_contains "$COMMAND_LOG" "gh pr comment 42 --body Updated this pull request from WordPress \`6.7.0\` to \`6.8.0\` instead of opening a new pull request. " assert_not_contains "$COMMAND_LOG" "gh pr create" teardown_case @@ -123,7 +123,7 @@ test_repairs_pull_request_metadata_after_push_succeeds() { "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" assert_contains "$COMMAND_LOG" "gh pr edit 42 --title Upgrade plugin to WordPress 6.8.0" - assert_contains "$COMMAND_LOG" 'gh pr comment 42 --body Updated this pull request from WordPress `6.7.0` to `6.8.0` instead of opening a new pull request. ' + assert_contains "$COMMAND_LOG" "gh pr comment 42 --body Updated this pull request from WordPress \`6.7.0\` to \`6.8.0\` instead of opening a new pull request. " assert_not_contains "$COMMAND_LOG" "git commit" assert_not_contains "$COMMAND_LOG" "git push" From ef6ece91a7c0aba89b74d5a5446c1072271eae82 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 8 Sep 2026 18:33:44 -0400 Subject: [PATCH 3/3] Expand action behavior coverage --- tests/check-upgrade.sh | 82 ++++++++++++++++++++++++++++++++++++++++-- tests/stubs/gh | 4 +++ tests/stubs/git | 4 +++ tests/stubs/npm | 3 ++ tests/stubs/npx | 3 ++ 5 files changed, 94 insertions(+), 2 deletions(-) create mode 100755 tests/stubs/npm create mode 100755 tests/stubs/npx diff --git a/tests/check-upgrade.sh b/tests/check-upgrade.sh index 886f9ff..add27ea 100755 --- a/tests/check-upgrade.sh +++ b/tests/check-upgrade.sh @@ -33,13 +33,13 @@ setup_case() { export UPGRADE_DEPENDENCIES=false export GITHUB_ACTOR=github-actions export GH_PR_LIST_OUTPUT=${1:-[]} - unset CHECKOUT_PLUGIN_VERSION GH_API_FAIL GH_PR_COMMENTS_OUTPUT GH_PR_LIST_FAIL PARENT_PLUGIN_VERSION WORDPRESS_VERSION + unset CHECKOUT_PLUGIN_VERSION GH_API_FAIL GH_PR_COMMENTS_OUTPUT GH_PR_EDIT_FAIL GH_PR_LIST_FAIL GIT_FETCH_FAIL PARENT_PLUGIN_VERSION WORDPRESS_VERSION printf '%s\n' ' "$PLUGIN_FILE" : > "$COMMAND_LOG" mkdir "$TEST_DIR/bin" - for command in curl date gh git sed sort; do + for command in curl date gh git npm npx sed sort; do ln -s "$ROOT_DIR/tests/stubs/$command" "$TEST_DIR/bin/$command" done @@ -191,6 +191,79 @@ test_stops_when_comment_lookup_fails() { echo "ok - stops when comment lookup fails" } +test_stops_before_github_when_default_branch_is_current() { + setup_case + printf '%s\n' ' "$PLUGIN_FILE" + + "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" + + assert_contains "$TEST_DIR/output.log" "Latest WordPress version and plugin-supported version are the same, no upgrade needed." + assert_not_contains "$COMMAND_LOG" "gh " + assert_not_contains "$COMMAND_LOG" "git " + + teardown_case + echo "ok - stops before GitHub when the default branch is current" +} + +test_stops_when_existing_branch_fetch_fails() { + setup_case '[{"number":42,"headRefName":"action/upgrade-to-6.7.0-1700000000","title":"Upgrade plugin to WordPress 6.7.0","isCrossRepository":false}]' + export GIT_FETCH_FAIL=true + + if "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" 2>&1; then + fail "Expected branch fetch failure to stop the action" + fi + + assert_not_contains "$COMMAND_LOG" "git checkout" + assert_not_contains "$COMMAND_LOG" "gh pr create" + + teardown_case + echo "ok - stops when the existing branch fetch fails" +} + +test_stops_when_pull_request_edit_fails() { + setup_case '[{"number":42,"headRefName":"action/upgrade-to-6.7.0-1700000000","title":"Upgrade plugin to WordPress 6.7.0","isCrossRepository":false}]' + export GH_PR_EDIT_FAIL=true + + if "$ROOT_DIR/check-upgrade.sh" > "$TEST_DIR/output.log" 2>&1; then + fail "Expected pull request edit failure to stop the action" + fi + + assert_not_contains "$COMMAND_LOG" "gh api" + assert_not_contains "$COMMAND_LOG" "gh pr comment" + assert_not_contains "$COMMAND_LOG" "gh pr create" + + teardown_case + echo "ok - stops when pull request edit fails" +} + +test_updates_dependencies_when_package_exists() { + setup_case + export UPGRADE_DEPENDENCIES=true + printf '{}\n' > "$TEST_DIR/package.json" + + (cd "$TEST_DIR" && "$ROOT_DIR/check-upgrade.sh") > "$TEST_DIR/output.log" + + assert_contains "$COMMAND_LOG" "npm ci" + assert_contains "$COMMAND_LOG" "npx wp-scripts packages-update --dist-tag=wp-6.8.0" + + teardown_case + echo "ok - updates dependencies when package.json exists" +} + +test_skips_dependencies_when_package_is_missing() { + setup_case + export UPGRADE_DEPENDENCIES=true + + (cd "$TEST_DIR" && "$ROOT_DIR/check-upgrade.sh") > "$TEST_DIR/output.log" + + assert_contains "$TEST_DIR/output.log" "package.json does not exist, skipping dependency upgrade." + assert_not_contains "$COMMAND_LOG" "npm " + assert_not_contains "$COMMAND_LOG" "npx " + + teardown_case + echo "ok - skips dependencies when package.json is missing" +} + test_updates_existing_pull_request test_skips_existing_pull_request_at_current_version test_creates_pull_request_when_none_exists @@ -200,3 +273,8 @@ test_does_not_duplicate_update_note_on_retry test_selects_newest_same_repository_action_pull_request test_stops_when_pull_request_lookup_fails test_stops_when_comment_lookup_fails +test_stops_before_github_when_default_branch_is_current +test_stops_when_existing_branch_fetch_fails +test_stops_when_pull_request_edit_fails +test_updates_dependencies_when_package_exists +test_skips_dependencies_when_package_is_missing diff --git a/tests/stubs/gh b/tests/stubs/gh index 11e8e50..9e0226c 100755 --- a/tests/stubs/gh +++ b/tests/stubs/gh @@ -2,6 +2,10 @@ printf 'gh %s\n' "$*" >> "$COMMAND_LOG" +if [ "$1 $2" = "pr edit" ] && [ "${GH_PR_EDIT_FAIL-}" = "true" ]; then + exit 1 +fi + if [ "$1 $2" = "pr list" ]; then if [ "${GH_PR_LIST_FAIL-}" = "true" ]; then exit 1 diff --git a/tests/stubs/git b/tests/stubs/git index dfd90a2..301c9c3 100755 --- a/tests/stubs/git +++ b/tests/stubs/git @@ -2,6 +2,10 @@ printf 'git %s\n' "$*" >> "$COMMAND_LOG" +if [ "$1" = "fetch" ] && [ "${GIT_FETCH_FAIL-}" = "true" ]; then + exit 1 +fi + if [ "$1" = "checkout" ] && [ -n "${CHECKOUT_PLUGIN_VERSION-}" ]; then printf '%s\n' ' "$PLUGIN_FILE" fi diff --git a/tests/stubs/npm b/tests/stubs/npm new file mode 100755 index 0000000..573c285 --- /dev/null +++ b/tests/stubs/npm @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +printf 'npm %s\n' "$*" >> "$COMMAND_LOG" diff --git a/tests/stubs/npx b/tests/stubs/npx new file mode 100755 index 0000000..2de8378 --- /dev/null +++ b/tests/stubs/npx @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +printf 'npx %s\n' "$*" >> "$COMMAND_LOG"