Skip to content

Instantly share code, notes, and snippets.

@Calinou
Last active October 4, 2023 19:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Calinou/9509da17ee3f3773ac6b47e5c2713c5e to your computer and use it in GitHub Desktop.
Save Calinou/9509da17ee3f3773ac6b47e5c2713c5e to your computer and use it in GitHub Desktop.
Test a Godot pull request locally
#!/usr/bin/env bash
#
# Tests a Godot pull request locally, given an URL to a pull request (or its
# number) and a path or URL to a testing project. This script can also be used
# to confirm Godot bug reports locally using "master" as the first argument.
#
#### Installation
#
# Save this script to a file in your PATH (such as `/usr/local/bin/gd-pr-test`),
# then make the file executable using `chmod +x /path/to/script`.
#
# Optional but recommended: Set the `GODOT_SOURCE_DIR` environment variable to
# the full path to a Godot source folder. This allows you to use this script
# without having to `cd` to the Godot source folder first.
# If you use Visual Studio Code or VSCodium, you can have a build task called
# "Build (editor)" (case-sensitive) in `.vscode/tasks.json` within the Godot
# source folder. If `vstask` is installed, this build task will be used instead
# of running SCons directly, which allows you to pass options in the same way
# you'd do in your code editor. `vstask` can be downloaded from
# https://github.com/cmccandless/vstask.
#
# If running SCons directly, set the `GODOT_SCONS_OPTIONS` environment variable
# to a string containing SCons options you'd like to pass when building.
#
# NOTE: This script is currently only supported on Linux. Support for other
# platforms may be added in the future.
#
#### Usage
#
# gd-pr-test
# <pull request number, URL or "master" to test on latest master branch>
# <path to testing project's ZIP (local or remote URL), folder, project.godot file or "new" to create a project>
# [--no-rebase]
#
#### MIT License
#
# Copyright © 2023-present Hugo Locurcio and contributors
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
set -euo pipefail
IFS=$'\n\t'
# Print a heading with a underline:
#
# Example
# -------
print_header() {
string="$1"
echo -e "\n\e[1m$string"
for ((i=1; i <= ${#string}; i++)); do
echo -n "▔"
done
echo -e "\e[0m"
}
handle_sigint() {
if [[ "${project_dir:-""}" == "" ]]; then
# Don't print anything if using Ctrl+C before the test project has started opening.
echo ""
exit 1
fi
print_header "Test project was closed by SIGINT (Ctrl+C)"
print_project_finish
}
print_project_finish() {
pull_request_url="https://github.com/godotengine/godot/pull/$pr_number"
echo -e "\e[92mDone testing pull request: \e[1;4m$pull_request_url\e[0m"
echo -e "\e[92mPath to testing project: \e[1;4m$project_dir\e[0m"
echo -e "\e[92mThe pull request was tested on top of \`master\` \e[4m$(git merge-base master HEAD)\e[0m"
echo -e "\e[90mMessage to use in review if successful:\n"
echo -e "\e[90mTested locally (rebased on top of \`master\` $(git merge-base master HEAD)), it works as expected.\e[0m"
}
trap handle_sigint SIGINT
if [[ "$#" -lt 2 ]]; then
echo -e "\e[1mUsage:\e[0m gd-pr-test"
echo -e " <pull request number, URL, or \"master\" to test on latest master branch>"
echo -e " <path to testing project's ZIP (local or remote URL), folder, project.godot file or \"new\" to create a project>"
echo -e " [--no-rebase]"
exit 1
fi
if [[ -n "${GODOT_SOURCE_DIR:-""}" ]]; then
cd "$GODOT_SOURCE_DIR"
fi
if [[ ! -e thirdparty/README.md ]]; then
echo -e "\e[1;91mError:\e[22m The current directory (\e[4m$(pwd)\e[24m) is not a Godot source repository folder."
echo -e " Consider setting the \e[4mGODOT_SOURCE_DIR\e[24m environment variable to the full path to a Godot source folder."
echo -e " When set, this will automatically change directories when using gd-pr-test.\e[0m"
exit 1
fi
if ! command -v curl > /dev/null; then
echo -e "\e[1;91mError:\e[22m curl must be installed and in PATH."
exit 1
fi
if ! command -v gh > /dev/null; then
echo -e "\e[1;91mError:\e[22m gh CLI must be installed and in PATH."
echo -e " \e[4mhttps://cli.github.com\e[0m"
exit 1
fi
pr_number="$(basename "$1")"
if [[ "$pr_number" != "master" ]]; then
print_header "Checking out pull request: $pr_number"
# Checkout the pull request and rebase it against local `master` if requested.
# Use a unique branch name to prevent accidentally overwriting local branches,
# or the same PRs that were manually checked out by the user.
git switch master
git pull
gh pr checkout "$1" --branch "gd-pr-test-$pr_number" --force
if [[ "${3:-x}" != "--no-rebase" ]]; then
print_header "Rebasing against the local \`master\` branch"
# Skip commit GPG signing during the rebase to avoid password prompts.
if ! git rebase master --no-gpg-sign; then
git rebase --abort
echo -e "\e[1;91mError:\e[22m Rebase has failed due to merge conflicts, aborting." \
echo -e " Try re-running the command with the \e[4m--no-rebase\e[24m option at the end." \
exit 1
fi
fi
else
print_header "Checking out branch: $pr_number"
git switch "$pr_number"
git pull
fi
if command -v vstask > /dev/null; then
print_header "Compiling Godot using vstask"
vstask "Build (editor)"
else
print_header "Compiling Godot using SCons"
# shellcheck disable=SC2086
scons ${GODOT_SCONS_FLAGS:-""}
fi
prefix=""
zipfile="$2"
# Prepare MRP for opening in the editor we've compiled.
if [[ -z "${2##*.zip}" ]]; then
if [[ -z "${2##https://*}" ]]; then
print_header "Downloading project ZIP archive"
zipfile="$(basename "$2")"
prefix="/tmp/"
curl -LO "$2" --output-dir "$prefix"
fi
if unzip -Z1 "$prefix$zipfile" | grep "^project.godot" > /dev/null; then
# `project.godot` is at the root of a ZIP archive. Create a subfolder with
# the same name as the ZIP (but without the extension) to avoid putting
# too many files in the root folder (and preventing other projects from
# being extracted).
unzip "$prefix$zipfile" -d "$prefix${zipfile%.zip}"
else
unzip "$prefix$zipfile" -d "$prefix"
fi
# Remove original ZIP archive after extracting it.
rm -f "$prefix$zipfile"
fi
if [[ "$2" == "new" ]]; then
print_header "Creating a new test project"
new_project_dir="/tmp/test_pr_${pr_number}"
mkdir -p "$new_project_dir"
touch "$new_project_dir/project.godot"
project_dir="$new_project_dir"
else
project_dir="$prefix${zipfile%.zip}"
fi
if [[ -z "${2#*/project.godot}" ]]; then
project_path="$project_dir"
else
project_path="$project_dir/project.godot"
fi
print_header "Opening: $project_path"
# Work around issue with self-compiled Godot binaries crashing on startup due to MangoHud injection:
# https://github.com/godotengine/godot/issues/75409
MANGOHUD=0 bin/godot.linuxbsd.editor.x86_64 "$project_path"
print_header "Test project was closed by exiting the editor"
print_project_finish
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment