Skip to content

Commit db9e6e2

Browse files
committed
Refactor reproducibility check
1 parent 52d63d4 commit db9e6e2

File tree

1 file changed

+73
-51
lines changed

1 file changed

+73
-51
lines changed

.github/workflows/repro_check.yml

+73-51
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,101 @@
1-
name: Build and Diff Projects
1+
# Workflow that runs after a merge to master, builds toolchain in 2 different
2+
# directories to check for reproducible builds. This check helps track which
3+
# commits cause reproducibility issues. This check should pass before stable
4+
# releases are made.
5+
6+
name: Reproducibility check
27

38
on:
49
push:
510
branches:
611
- master
7-
pull_request:
8-
branches:
9-
- master
10-
- reproducible
1112

1213
jobs:
1314
build_and_compare:
14-
runs-on: ubuntu-latest
15-
15+
runs-on: ubuntu-24.04
1616
steps:
1717
- name: Checkout repository
18-
uses: actions/checkout@v2
19-
20-
- name: Set up Python
21-
uses: actions/setup-python@v2
22-
with:
23-
python-version: '3.x' # Adjust to the version you need
18+
uses: actions/checkout@v4
2419

25-
- name: Build and store buildA binaries
20+
- name: Build and store toolchains
2621
run: |
27-
mkdir ../buildA
28-
cp -r "$(pwd)" ../buildA
29-
pushd ../buildA
30-
SOURCE_DIR=$(dirname $(find . -maxdepth 2 -name x.py))
31-
$SOURCE_DIR/configure --set rust.channel=nightly
32-
$SOURCE_DIR/x.py build --stage 2 -j$(($(nproc)*2/3))
33-
rm -rf $SOURCE_DIR
34-
STAGE2_DIR=`find build -name stage2`
35-
cp -r "$STAGE2_DIR" .
36-
echo "Contents stage 2 dir : `ls stage2`"
37-
rm -rf build
38-
popd
39-
40-
- name: Build and store buildA_extended binaries
41-
run: |
42-
mkdir ../buildA_extended
43-
cp -r "$(pwd)" ../buildA_extended
44-
pushd ../buildA_extended
45-
SOURCE_DIR=$(dirname $(find . -maxdepth 2 -name x.py))
46-
$SOURCE_DIR/configure --set rust.channel=nightly
47-
$SOURCE_DIR/x.py build --stage 2 -j$(($(nproc)*2/3))
48-
rm -rf $SOURCE_DIR
49-
STAGE2_DIR=`find build -name stage2`
50-
cp -r "$STAGE2_DIR" .
51-
echo "Contents stage 2 dir : `ls stage2`"
52-
rm -rf build
53-
popd
54-
55-
- name: Compare builds and archive artifacts
22+
# Define build function
23+
build_toolchain() {
24+
local dir_name="$1"
25+
echo "Building in $dir_name..."
26+
27+
mkdir "../$dir_name"
28+
cp -r . "../$dir_name/rust"
29+
pushd "../$dir_name"
30+
31+
# Find source directory
32+
SOURCE_DIR="./rust"
33+
34+
# FIXME: Setting channel to nightly because only nightly builds succeed on CI
35+
$SOURCE_DIR/configure --set rust.channel=nightly
36+
37+
# Build rust till stage 2
38+
$SOURCE_DIR/x.py build --stage 2
39+
40+
# Remove copy of source directory to save space
41+
rm -rf "$SOURCE_DIR"
42+
43+
# Save stage2 directory
44+
STAGE2_DIR=$(find build -name stage2)
45+
cp -r "$STAGE2_DIR" .
46+
echo "Contents of stage2 dir in $dir_name: $(ls stage2)"
47+
48+
# Clean up to save space
49+
rm -rf build
50+
popd
51+
}
52+
53+
# Build both
54+
build_toolchain buildA
55+
build_toolchain buildA_extended
56+
57+
# Compare the two builds
58+
- name: Compare builds
59+
id: compare
5660
run: |
5761
# Ensure the directories exist
5862
if [[ ! -d "../buildA" || ! -d "../buildA_extended" ]]; then
5963
echo "Error: Build directories not found!"
6064
exit 1
6165
fi
66+
mv ../buildA ../buildA_extended .
67+
# Perform a recursive diff between the stage2 directories of both builds
68+
# If there are differences, record the result so we can upload artifacts and then fail later
69+
# The binaries should be identical, so the cause of difference should be analysed and fixed
70+
# appropriately.
71+
if diff -r buildA/stage2 buildA_extended/stage2; then
72+
echo "No differences found."
73+
echo "has_diff=false" >> $GITHUB_OUTPUT
74+
else
75+
echo "Differences found!"
76+
echo "has_diff=true" >> $GITHUB_OUTPUT
77+
fi
6278
63-
# Perform a diff between the two builds
64-
diff -r ../buildA/stage2 ../buildA_extended/stage2 || echo "Differences found!"
65-
66-
tar -czf buildA.tar.gz ../buildA
67-
tar -czf buildA_extended.tar.gz ../buildA_extended
68-
79+
# Upload buildA and buildA_extended directories as an artifact (for debugging purposes)
80+
# The artifacts contain the stage2 folder from both builds. The artifact are
81+
# helpful to debug the reproducibility issue when this test fails.
6982
- name: Upload buildA artifact
83+
if: steps.compare.outputs.has_diff == 'true'
7084
uses: actions/upload-artifact@v4
7185
with:
7286
name: buildA
73-
path: buildA.tar.gz
87+
path: buildA
7488

7589
- name: Upload buildA_extended artifact
90+
if: steps.compare.outputs.has_diff == 'true'
7691
uses: actions/upload-artifact@v4
7792
with:
7893
name: buildA_extended
79-
path: buildA_extended.tar.gz
94+
path: buildA_extended
95+
96+
# Fail the job if differences were found between the builds
97+
- name: Fail the job if there are differences
98+
if: steps.compare.outputs.has_diff == 'true'
99+
run: |
100+
echo "Differences found between buildA and buildA_extended, Reproducibility check failed"
101+
exit 1

0 commit comments

Comments
 (0)