Skip to content

Commit

Permalink
Rewrite run_checks.sh
Browse files Browse the repository at this point in the history
  • Loading branch information
cl8n committed Dec 1, 2023
1 parent f00fd97 commit f020510
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 104 deletions.
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ RUN npm install && npm install -g osu-wiki && pip3 install -r requirements.txt
# Run the container with UID and GID of the host
COPY meta/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]

# By default, run all checks when the container is started
CMD ["meta/check-all.sh"]
68 changes: 68 additions & 0 deletions meta/check-all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/sh

set -eu

test_output_pipe=/tmp/osu-wiki-test-output-pipe
rm -f "$test_output_pipe"
mkfifo "$test_output_pipe"

run_test() {
test_name="$1"
shift

printf '\033[1m## Running %s test...\033[m\n' "$test_name" >&2

# Run the test as a job, preserving its original stdin on fd 4, and directing
# all of its output to a pipe opened for reading on fd 3
exec 4<&0
"$@" <&4 >"$test_output_pipe" 2>&1 &
exec 3<"$test_output_pipe"

# If the test has output, print the first line with a preceding newline
if IFS= read -r first_line <&3; then
printf '\n%s\n' "$first_line" >&2
fi

# Stream the rest of the test's output
cat <&3 >&2

# If the test had output, print another newline
if test -n "$first_line"; then
printf '\n' >&2
fi

# Print the final message based on the exit code of the test
if wait $!; then
printf '\033[1;32m## Passed %s test.\033[m\n' "$test_name" >&2
else
printf '\033[1;31m## Failed %s test.\033[m\n' "$test_name" >&2
fi

# Close fd 3 and fd 4
exec 3<&- 4<&-
}

cd -- "$(dirname "$0")/.."

changed_files="$(
{
git diff --diff-filter=d --name-only --no-renames master
git ls-files --exclude-standard --others
} | sort -u
)"

if test -z "$changed_files"; then
printf 'No files changed since master.\n' >&2
exit
fi

printf '%s\n' "$changed_files" | run_test 'file size' xargs meta/check-file-sizes.sh
{ printf '%s\n' "$changed_files" | grep '\.md$' || true; } | run_test Remark xargs -r meta/remark.sh
run_test 'YAML style' osu-wiki-tools check-yaml
run_test link osu-wiki-tools check-links --all

first_commit_hash="$(git log --pretty=%H master.. | tail -n 1)"

if test -n "$first_commit_hash"; then
run_test 'outdated article' osu-wiki-tools check-outdated-articles --base-commit "$first_commit_hash" --workflow
fi
20 changes: 20 additions & 0 deletions meta/docker-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh

set -eu

osu_wiki_path="$(cd -- "$(dirname "$0")/.." && pwd)"
remove_node_modules="$(test -e "$osu_wiki_path/node_modules" || printf 1)"

# Map the host repo directory to /osu-wiki, but use node_modules from the image
docker run \
--rm \
--volume "$osu_wiki_path:/osu-wiki" \
--volume /osu-wiki/node_modules/ \
osu-wiki "$@"

# FIXME: The above command leaves behind an empty node_modules directory if it
# didn't already exist, and I can't figure out how to prevent that... so
# here I delete the node_modules directory if it is new. —clayton
if test -n "$remove_node_modules"; then
rm -rf "$osu_wiki_path/node_modules"
fi
126 changes: 22 additions & 104 deletions run-checks.sh
Original file line number Diff line number Diff line change
@@ -1,117 +1,35 @@
#!/bin/bash
#!/bin/sh

function print_error() { printf -- "\e[0;31m$1\e[m\n" 1>&2; }
function print_warning() { printf -- "\e[0;34m$1\e[m\n" 1>&2; }
function print_success() { printf -- "\e[0;32m$1\e[m\n" 1>&2; }
function print_ok() { printf -- "$1\n" 1>&2; }
set -eu

function _build_container() {
if ! ( which docker > /dev/null ); then
print_error "Missing Docker -- install it from https://docs.docker.com/engine and restart the shell."
build_docker_image() {
if ! which docker >/dev/null 2>&1; then
printf '\033[31mError:\033[m Docker not found. Install it from https://docs.docker.com/get-docker/ and restart the shell.\n' >&2
exit 1
fi

print_ok "Preparing the Docker image..."
if ! ( DOCKER_BUILDKIT=1 docker build -q -t osu-wiki . ); then
print_error "Failed to build the Docker image."
if ! DOCKER_BUILDKIT=1 docker build --tag osu-wiki . >/dev/null; then
printf '\033[31mError:\033[m Failed to build Docker image.\n' >&2
exit 1
fi
}

# Do not shadow node_modules in the container: https://stackoverflow.com/q/29181032#comment97216954_37898591
function _docker() {
osu_wiki_root=$( cd -- "$( dirname $0 )" && pwd )
container_workdir="/osu-wiki"
docker run \
--volume ${osu_wiki_root}:${container_workdir}/ \
--volume ${container_workdir}/node_modules \
--workdir ${container_workdir} osu-wiki bash -c "$*"
}

function _test_wrapper() {
test_name="$1"
command_line="$2"
files=( $( echo "${@: 3}" | tr '\n' ' ' ) ) # bash v3.2 on macOS doesn't support readarray

if test -z "$files"; then
print_success "* Skipped $test_name test."
else
print_ok "* Run $test_name test"
$command_line "${files[@]}"
return_code=$?
if test $return_code -eq 0; then
print_success "* Passed $test_name test."
else
print_error "* Failed $test_name test (exit code $return_code)."
fi
fi
}

function _usage() {
echo "Usage: $( basename $0 ) [-- [COMMAND] [ARGS]]"
echo -e "Run osu! wiki-related commands in a Docker container.\n"
echo -e "Without arguments, run default test suite on all changes, both committed and not.\n"
echo " -- [COMMAND] [ARGS] run COMMAND in the container, passing ARGS as its arguments"
}

function main() {
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
_usage
exit 2
;;
--)
shift
_build_container
_docker "$@"
exit $?
;;
*|-*|--*)
echo -e "Unrecognized option '$1'\nTry '$( basename $0 ) --help' for more information."
exit 1
;;
esac
done

current_branch=$( git branch --show-current )
if test ${current_branch} = 'master'; then
print_error "Please run this from a feature branch, i.e. not 'master'"
exit 1
fi

first_commit_hash=$( git log master..${current_branch} --pretty=format:%H | tail -1 )
cd -- "$(dirname "$0")"

interesting_files=$(
sort -u < <(
# Changes that are not committed (staged + unstaged + untracked), but without deleted files
git status --short -v -v --no-renames --porcelain | awk '$1 != "D" { print $2 }'
# Changes committed so far (may overlap with the above)
if [[ -n ${first_commit_hash} ]]; then
git diff --no-renames --name-only --diff-filter=d ${first_commit_hash}^
fi
)
)

if test -z "${interesting_files}"; then
print_success "No changes detected -- nothing to check."
exit 0
if test $# -gt 0; then
if test $# -gt 1 -a "$1" = --; then
shift
build_docker_image
exec meta/docker-run.sh "$@"
fi

# ppy/osu-wiki#8867 -- disable style checks for non-article Markdown files, such as README.md
interesting_articles=$( echo "${interesting_files}" | grep -e ^wiki/ -e ^news/ | grep .md$ | grep -E -v '^[A-Z-]+\.md$' )

_build_container

# TODO give no arguments to check-file-sizes
_test_wrapper "file size" "_docker meta/check-file-sizes.sh" "${interesting_files}"
_test_wrapper "article style" "_docker meta/remark.sh" "${interesting_articles}"

_test_wrapper "YAML style" "_docker osu-wiki-tools check-yaml --target" .

# TODO: _test_wrapper expects a third argument but luckily --all overrides --target. please rewrite to make this prettier
_test_wrapper "link" "_docker osu-wiki-tools check-links --all --target" "${interesting_articles}"
_test_wrapper "article freshness" "_docker osu-wiki-tools check-outdated-articles --workflow --base-commit" "${first_commit_hash}"
}
exec >&2
printf 'Run the test suite on files changed since master:\n\n'
printf ' \033[4m%s\033[m\n\n' "$0"
printf 'Run a command in the osu-wiki Docker container:\n\n'
printf ' \033[4m%s\033[m -- <command> [<arguments>]\n' "$0"
exit 1
fi

main $@
build_docker_image
exec meta/docker-run.sh

0 comments on commit f020510

Please sign in to comment.