Skip to content

Commit 4f8cb89

Browse files
committed
Refactor reproducibility check
1 parent 95ef2f5 commit 4f8cb89

File tree

1 file changed

+75
-49
lines changed

1 file changed

+75
-49
lines changed

.github/workflows/repro_check.yml

+75-49
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,105 @@
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+
# release are made.
5+
6+
name: Reproducibility check
27

38
on:
49
push:
5-
branches:
6-
- master
7-
pull_request:
810
branches:
911
- master
1012
- reproducible
1113

1214
jobs:
1315
build_and_compare:
14-
runs-on: ubuntu-latest
15-
16+
runs-on: ubuntu-24.04
1617
steps:
1718
- 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
19+
uses: actions/checkout@v4
2420

25-
- name: Build and store buildA binaries
26-
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
21+
- name: Build and store toolchains
4122
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
23+
# Define build function
24+
build_toolchain() {
25+
local dir_name="$1"
26+
echo "Building in $dir_name..."
27+
28+
mkdir "../$dir_name"
29+
cp -r "$(pwd)" "../$dir_name"
30+
pushd "../$dir_name"
31+
32+
# Find source directory
33+
SOURCE_DIR=$(dirname $(find . -maxdepth 2 -name x.py))
34+
35+
# FIXME: Setting channel to nightly because only nightly builds succeed on CI
36+
$SOURCE_DIR/configure --set rust.channel=nightly
37+
38+
# Build rust till stage 2
39+
$SOURCE_DIR/x.py build --stage 2 -j$(($(nproc)*2/3))
40+
41+
# Remove copy of source directory to save space
42+
rm -rf "$SOURCE_DIR"
43+
44+
# Save stage2 directory
45+
STAGE2_DIR=$(find build -name stage2)
46+
cp -r "$STAGE2_DIR" .
47+
echo "Contents of stage2 dir in $dir_name: $(ls stage2)"
48+
49+
# Clean up to save space
50+
rm -rf build
51+
popd
52+
}
53+
54+
# Build both
55+
build_toolchain buildA
56+
build_toolchain buildA_extended
57+
58+
# Compare the two builds
59+
- name: Compare builds
60+
id: compare
5661
run: |
5762
# Ensure the directories exist
5863
if [[ ! -d "../buildA" || ! -d "../buildA_extended" ]]; then
5964
echo "Error: Build directories not found!"
6065
exit 1
6166
fi
6267
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+
# Perform a recursive diff between the stage2 directories of both builds
69+
# If there are differences, record the result so we can upload artifacts and then fail later
70+
# The binaries should be identical, so the cause of difference should be analysed and fixed
71+
# appropriately.
72+
if diff -r ../buildA/stage2 ../buildA_extended/stage2; then
73+
echo "No differences found."
74+
echo "has_diff=false" >> $GITHUB_OUTPUT
75+
else
76+
echo "Differences found!"
77+
echo "has_diff=true" >> $GITHUB_OUTPUT
78+
fi
6879
80+
# Upload buildA directory as an artifact (for debugging purposes)
81+
# This artifact contains stage2 folder from buildA. This artifact would
82+
# be helpful to debug reproducibility issue when this test fails.
6983
- name: Upload buildA artifact
84+
if: steps.compare.outputs.has_diff == 'true'
7085
uses: actions/upload-artifact@v4
7186
with:
7287
name: buildA
73-
path: buildA.tar.gz
88+
path: ../buildA
7489

90+
# Upload buildA_extended directory as an artifact (for debugging purposes)
91+
# This artifact contains stage2 folder from buildA_extended. This artifact would
92+
# be helpful to debug reproducibility issue when this test fails.
7593
- name: Upload buildA_extended artifact
94+
if: steps.compare.outputs.has_diff == 'true'
7695
uses: actions/upload-artifact@v4
7796
with:
7897
name: buildA_extended
79-
path: buildA_extended.tar.gz
98+
path: ../buildA_extended
99+
100+
# Fail the job if differences were found between the builds
101+
- name: Fail the job if there are differences
102+
if: steps.compare.outputs.has_diff == 'true'
103+
run: |
104+
echo "Differences found between buildA and buildA_extended, Reproducibility check failed"
105+
exit 1

0 commit comments

Comments
 (0)