]> git.lizzy.rs Git - rust.git/blob - src/ci/docker/x86_64-gnu-tools/checktools.sh
Auto merge of #65838 - estebank:resilient-recovery, r=Centril
[rust.git] / src / ci / docker / x86_64-gnu-tools / checktools.sh
1 #!/bin/sh
2
3 set -eu
4
5 X_PY="$1"
6 TOOLSTATE_FILE="$(realpath -m $2)"
7 OS="$3"
8 COMMIT="$(git rev-parse HEAD)"
9 CHANGED_FILES="$(git diff --name-status HEAD HEAD^)"
10 SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))"
11 # ^ Number of days after the last promotion of beta.
12 #   Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens.
13 #   The Wednesday after this has value 0.
14 #   We track this value to prevent regressing tools in the last week of the 6-week cycle.
15
16 mkdir -p "$(dirname $TOOLSTATE_FILE)"
17 touch "$TOOLSTATE_FILE"
18
19 # Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
20
21 set +e
22 python2.7 "$X_PY" test --no-fail-fast \
23     src/doc/book \
24     src/doc/nomicon \
25     src/doc/reference \
26     src/doc/rust-by-example \
27     src/doc/embedded-book \
28     src/doc/edition-guide \
29     src/doc/rustc-guide \
30     src/tools/clippy \
31     src/tools/rls \
32     src/tools/rustfmt \
33     src/tools/miri \
34
35 set -e
36
37 cat "$TOOLSTATE_FILE"
38 echo
39
40 # This function checks if a particular tool is *not* in status "test-pass".
41 check_tool_failed() {
42     grep -vq '"'"$1"'":"test-pass"' "$TOOLSTATE_FILE"
43 }
44
45 # This function checks that if a tool's submodule changed, the tool's state must improve
46 verify_submodule_changed() {
47     echo "Verifying status of $1..."
48     if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then
49         echo "This PR updated '$2', verifying if status is 'test-pass'..."
50         if check_tool_failed "$1"; then
51             echo
52             echo "⚠️ We detected that this PR updated '$1', but its tests failed."
53             echo
54             echo "If you do intend to update '$1', please check the error messages above and"
55             echo "commit another update."
56             echo
57             echo "If you do NOT intend to update '$1', please ensure you did not accidentally"
58             echo "change the submodule at '$2'. You may ask your reviewer for the"
59             echo "proper steps."
60             exit 3
61         fi
62     fi
63 }
64
65 # deduplicates the submodule check and the assertion that on beta some tools MUST be passing.
66 # $1 should be "submodule_changed" to only check tools that got changed by this PR,
67 # or "beta_required" to check all tools that have $2 set to "beta".
68 check_dispatch() {
69     if [ "$1" = submodule_changed ]; then
70         # ignore $2 (branch id)
71         verify_submodule_changed $3 $4
72     elif [ "$2" = beta ]; then
73         echo "Requiring test passing for $3..."
74         if check_tool_failed "$3"; then
75             exit 4
76         fi
77     fi
78 }
79
80 # List all tools here.
81 # This function gets called with "submodule_changed" for each PR that changed a submodule,
82 # and with "beta_required" for each PR that lands on beta/stable.
83 # The purpose of this function is to *reject* PRs if a tool is not "test-pass" and
84 # (a) the tool's submodule has been updated, or (b) we landed on beta/stable and the
85 # tool has to "test-pass" on that branch.
86 status_check() {
87     check_dispatch $1 beta book src/doc/book
88     check_dispatch $1 beta nomicon src/doc/nomicon
89     check_dispatch $1 beta reference src/doc/reference
90     check_dispatch $1 beta rust-by-example src/doc/rust-by-example
91     check_dispatch $1 beta edition-guide src/doc/edition-guide
92     check_dispatch $1 beta rls src/tools/rls
93     check_dispatch $1 beta rustfmt src/tools/rustfmt
94     check_dispatch $1 beta clippy-driver src/tools/clippy
95     # These tools are not required on the beta/stable branches, but they *do* cause
96     # PRs to fail if a submodule update does not fix them.
97     # They will still cause failure during the beta cutoff week, unless `checkregression.py`
98     # exempts them from that.
99     check_dispatch $1 nightly miri src/tools/miri
100     check_dispatch $1 nightly embedded-book src/doc/embedded-book
101     check_dispatch $1 nightly rustc-guide src/doc/rustc-guide
102 }
103
104 # If this PR is intended to update one of these tools, do not let the build pass
105 # when they do not test-pass.
106
107 status_check "submodule_changed"
108
109 CHECK_NOT="$(readlink -f "$(dirname $0)/checkregression.py")"
110 # This callback is called by `commit_toolstate_change`, see `repo.sh`.
111 change_toolstate() {
112     # only update the history
113     if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then
114         echo 'Toolstate is not changed. Not updating.'
115     else
116         if [ $SIX_WEEK_CYCLE -ge 35 ]; then
117             # Reject any regressions during the week before beta cutoff.
118             python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed
119         fi
120         sed -i "1 a\\
121 $COMMIT\t$(cat "$TOOLSTATE_FILE")
122 " "history/$OS.tsv"
123     fi
124 }
125
126 if [ "$RUST_RELEASE_CHANNEL" = nightly ]; then
127     if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then
128         . "$(dirname $0)/repo.sh"
129         MESSAGE_FILE=$(mktemp -t msg.XXXXXX)
130         echo "($OS CI update)" > "$MESSAGE_FILE"
131         commit_toolstate_change "$MESSAGE_FILE" change_toolstate
132         rm -f "$MESSAGE_FILE"
133     fi
134     exit 0
135 fi
136
137 # abort compilation if an important tool doesn't build
138 # (this code is reachable if not on the nightly channel)
139 status_check "beta_required"