blob: ebb8c0bda53ee2ae3654a1d9e28388b2eeafcb07 [file] [log] [blame]
set -eu
TOOLSTATE_FILE="$(realpath -m $2)"
COMMIT="$(git rev-parse HEAD)"
CHANGED_FILES="$(git diff --name-status HEAD HEAD^)"
SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))"
# ^ Number of days after the last promotion of beta.
# Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens.
# The Wednesday after this has value 0.
# We track this value to prevent regressing tools in the last week of the 6-week cycle.
mkdir -p "$(dirname $TOOLSTATE_FILE)"
# Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
set +e
python2.7 "$X_PY" test --no-fail-fast \
src/doc/book \
src/doc/nomicon \
src/doc/reference \
src/doc/rust-by-example \
src/doc/embedded-book \
src/doc/edition-guide \
src/doc/rustc-guide \
src/tools/clippy \
src/tools/rls \
src/tools/rustfmt \
src/tools/miri \
set -e
# This function checks if a particular tool is *not* in status "test-pass".
check_tool_failed() {
grep -vq '"'"$1"'":"test-pass"' "$TOOLSTATE_FILE"
# This function checks that if a tool's submodule changed, the tool's state must improve
verify_submodule_changed() {
echo "Verifying status of $1..."
if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then
echo "This PR updated '$2', verifying if status is 'test-pass'..."
if check_tool_failed "$1"; then
echo "⚠️ We detected that this PR updated '$1', but its tests failed."
echo "If you do intend to update '$1', please check the error messages above and"
echo "commit another update."
echo "If you do NOT intend to update '$1', please ensure you did not accidentally"
echo "change the submodule at '$2'. You may ask your reviewer for the"
echo "proper steps."
exit 3
# deduplicates the submodule check and the assertion that on beta some tools MUST be passing.
# $1 should be "submodule_changed" to only check tools that got changed by this PR,
# or "beta_required" to check all tools that have $2 set to "beta".
check_dispatch() {
if [ "$1" = submodule_changed ]; then
# ignore $2 (branch id)
verify_submodule_changed $3 $4
elif [ "$2" = beta ]; then
echo "Requiring test passing for $3..."
if check_tool_failed "$3"; then
exit 4
# List all tools here.
# This function gets called with "submodule_changed" for each PR that changed a submodule,
# and with "beta_required" for each PR that lands on beta/stable.
# The purpose of this function is to *reject* PRs if a tool is not "test-pass" and
# (a) the tool's submodule has been updated, or (b) we landed on beta/stable and the
# tool has to "test-pass" on that branch.
status_check() {
check_dispatch $1 beta book src/doc/book
check_dispatch $1 beta nomicon src/doc/nomicon
check_dispatch $1 beta reference src/doc/reference
check_dispatch $1 beta rust-by-example src/doc/rust-by-example
check_dispatch $1 beta edition-guide src/doc/edition-guide
check_dispatch $1 beta rls src/tools/rls
check_dispatch $1 beta rustfmt src/tools/rustfmt
check_dispatch $1 beta clippy-driver src/tools/clippy
# These tools are not required on the beta/stable branches, but they *do* cause
# PRs to fail if a submodule update does not fix them.
# They will still cause failure during the beta cutoff week, unless ``
# exempts them from that.
check_dispatch $1 nightly miri src/tools/miri
check_dispatch $1 nightly embedded-book src/doc/embedded-book
check_dispatch $1 nightly rustc-guide src/doc/rustc-guide
# If this PR is intended to update one of these tools, do not let the build pass
# when they do not test-pass.
status_check "submodule_changed"
CHECK_NOT="$(readlink -f "$(dirname $0)/")"
# This callback is called by `commit_toolstate_change`, see ``.
change_toolstate() {
# only update the history
if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then
echo 'Toolstate is not changed. Not updating.'
if [ $SIX_WEEK_CYCLE -ge 35 ]; then
# Reject any regressions during the week before beta cutoff.
python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed
sed -i "1 a\\
" "history/$OS.tsv"
if [ "$RUST_RELEASE_CHANNEL" = nightly ]; then
if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then
. "$(dirname $0)/"
MESSAGE_FILE=$(mktemp -t msg.XXXXXX)
echo "($OS CI update)" > "$MESSAGE_FILE"
commit_toolstate_change "$MESSAGE_FILE" change_toolstate
exit 0
# abort compilation if an important tool doesn't build
# (this code is reachable if not on the nightly channel)
status_check "beta_required"