Last active
October 4, 2023 19:28
-
-
Save Calinou/9509da17ee3f3773ac6b47e5c2713c5e to your computer and use it in GitHub Desktop.
Test a Godot pull request locally
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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