From 84910a52fec290b3f3ee3689092479d18aaf111c Mon Sep 17 00:00:00 2001 From: B I Mohammed Abbas Date: Tue, 15 Apr 2025 13:41:23 +0530 Subject: [PATCH 1/3] Add reproducibility check --- .github/workflows/repro_check.yml | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .github/workflows/repro_check.yml diff --git a/.github/workflows/repro_check.yml b/.github/workflows/repro_check.yml new file mode 100644 index 0000000000000..337bf7c26a060 --- /dev/null +++ b/.github/workflows/repro_check.yml @@ -0,0 +1,87 @@ +name: Build and Diff Projects + +on: + push: + branches: + - master + pull_request: + branches: + - master + - reproducible + +jobs: + build_and_compare: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' # Adjust to the version you need + + - name: Build and store buildA binaries + run: | + mkdir ../buildA + cp -r "$(pwd)" ../buildA + pushd ../buildA + SOURCE_DIR=$(dirname $(find . -maxdepth 2 -name x.py)) + $SOURCE_DIR/configure --set rust.channel=nightly + $SOURCE_DIR/x.py build --stage 2 -j$(($(nproc)*2/3)) + rm -rf $SOURCE_DIR + STAGE2_DIR=`find build -name stage2` + cp -r "$STAGE2_DIR" . + echo "Contents stage 2 dir : `ls stage2`" + rm -rf build + popd + + - name: Build and store buildA_extended binaries + run: | + mkdir ../buildA_extended + cp -r "$(pwd)" ../buildA_extended + pushd ../buildA_extended + SOURCE_DIR=$(dirname $(find . -maxdepth 2 -name x.py)) + $SOURCE_DIR/configure --set rust.channel=nightly + $SOURCE_DIR/x.py build --stage 2 -j$(($(nproc)*2/3)) + rm -rf $SOURCE_DIR + STAGE2_DIR=`find build -name stage2` + cp -r "$STAGE2_DIR" . + echo "Contents stage 2 dir : `ls stage2`" + rm -rf build + popd + + - name: Compare builds and archive artifacts + run: | + sudo apt-get update + sudo apt-get install -y diffoscope + # Ensure the directories exist + if [[ ! -d "../buildA" || ! -d "../buildA_extended" ]]; then + echo "Error: Build directories not found!" + exit 1 + fi + + # Perform a diff between the two builds + diffoscope ../buildA/stage2 ../buildA_extended/stage2 > diffoscope_output.txt || echo "Differences found!" + + tar -czf buildA.tar.gz ../buildA + tar -czf buildA_extended.tar.gz ../buildA_extended + + - name: Upload diffoscope output + uses: actions/upload-artifact@v4 + with: + name: diffoscope-report + path: diffoscope_output.txt + + - name: Upload buildA artifact + uses: actions/upload-artifact@v4 + with: + name: buildA + path: buildA.tar.gz + + - name: Upload buildA_extended artifact + uses: actions/upload-artifact@v4 + with: + name: buildA_extended + path: buildA_extended.tar.gz From 52d63d4e549c43d4de43bf7cf280eba99254e77a Mon Sep 17 00:00:00 2001 From: B I Mohammed Abbas Date: Mon, 21 Apr 2025 09:06:29 +0530 Subject: [PATCH 2/3] remove diffoscope --- .github/workflows/repro_check.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/repro_check.yml b/.github/workflows/repro_check.yml index 337bf7c26a060..4f5d90cd037fb 100644 --- a/.github/workflows/repro_check.yml +++ b/.github/workflows/repro_check.yml @@ -54,8 +54,6 @@ jobs: - name: Compare builds and archive artifacts run: | - sudo apt-get update - sudo apt-get install -y diffoscope # Ensure the directories exist if [[ ! -d "../buildA" || ! -d "../buildA_extended" ]]; then echo "Error: Build directories not found!" @@ -63,17 +61,11 @@ jobs: fi # Perform a diff between the two builds - diffoscope ../buildA/stage2 ../buildA_extended/stage2 > diffoscope_output.txt || echo "Differences found!" + diff -r ../buildA/stage2 ../buildA_extended/stage2 || echo "Differences found!" tar -czf buildA.tar.gz ../buildA tar -czf buildA_extended.tar.gz ../buildA_extended - - name: Upload diffoscope output - uses: actions/upload-artifact@v4 - with: - name: diffoscope-report - path: diffoscope_output.txt - - name: Upload buildA artifact uses: actions/upload-artifact@v4 with: From db9e6e2353e76606d48c9624b284714450202a12 Mon Sep 17 00:00:00 2001 From: B I Mohammed Abbas Date: Wed, 23 Apr 2025 11:14:19 +0530 Subject: [PATCH 3/3] Refactor reproducibility check --- .github/workflows/repro_check.yml | 124 ++++++++++++++++++------------ 1 file changed, 73 insertions(+), 51 deletions(-) diff --git a/.github/workflows/repro_check.yml b/.github/workflows/repro_check.yml index 4f5d90cd037fb..9a05331fd18fd 100644 --- a/.github/workflows/repro_check.yml +++ b/.github/workflows/repro_check.yml @@ -1,79 +1,101 @@ -name: Build and Diff Projects +# Workflow that runs after a merge to master, builds toolchain in 2 different +# directories to check for reproducible builds. This check helps track which +# commits cause reproducibility issues. This check should pass before stable +# releases are made. + +name: Reproducibility check on: push: branches: - master - pull_request: - branches: - - master - - reproducible jobs: build_and_compare: - runs-on: ubuntu-latest - + runs-on: ubuntu-24.04 steps: - name: Checkout repository - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' # Adjust to the version you need + uses: actions/checkout@v4 - - name: Build and store buildA binaries + - name: Build and store toolchains run: | - mkdir ../buildA - cp -r "$(pwd)" ../buildA - pushd ../buildA - SOURCE_DIR=$(dirname $(find . -maxdepth 2 -name x.py)) - $SOURCE_DIR/configure --set rust.channel=nightly - $SOURCE_DIR/x.py build --stage 2 -j$(($(nproc)*2/3)) - rm -rf $SOURCE_DIR - STAGE2_DIR=`find build -name stage2` - cp -r "$STAGE2_DIR" . - echo "Contents stage 2 dir : `ls stage2`" - rm -rf build - popd - - - name: Build and store buildA_extended binaries - run: | - mkdir ../buildA_extended - cp -r "$(pwd)" ../buildA_extended - pushd ../buildA_extended - SOURCE_DIR=$(dirname $(find . -maxdepth 2 -name x.py)) - $SOURCE_DIR/configure --set rust.channel=nightly - $SOURCE_DIR/x.py build --stage 2 -j$(($(nproc)*2/3)) - rm -rf $SOURCE_DIR - STAGE2_DIR=`find build -name stage2` - cp -r "$STAGE2_DIR" . - echo "Contents stage 2 dir : `ls stage2`" - rm -rf build - popd - - - name: Compare builds and archive artifacts + # Define build function + build_toolchain() { + local dir_name="$1" + echo "Building in $dir_name..." + + mkdir "../$dir_name" + cp -r . "../$dir_name/rust" + pushd "../$dir_name" + + # Find source directory + SOURCE_DIR="./rust" + + # FIXME: Setting channel to nightly because only nightly builds succeed on CI + $SOURCE_DIR/configure --set rust.channel=nightly + + # Build rust till stage 2 + $SOURCE_DIR/x.py build --stage 2 + + # Remove copy of source directory to save space + rm -rf "$SOURCE_DIR" + + # Save stage2 directory + STAGE2_DIR=$(find build -name stage2) + cp -r "$STAGE2_DIR" . + echo "Contents of stage2 dir in $dir_name: $(ls stage2)" + + # Clean up to save space + rm -rf build + popd + } + + # Build both + build_toolchain buildA + build_toolchain buildA_extended + +# Compare the two builds + - name: Compare builds + id: compare run: | # Ensure the directories exist if [[ ! -d "../buildA" || ! -d "../buildA_extended" ]]; then echo "Error: Build directories not found!" exit 1 fi + mv ../buildA ../buildA_extended . + # Perform a recursive diff between the stage2 directories of both builds + # If there are differences, record the result so we can upload artifacts and then fail later + # The binaries should be identical, so the cause of difference should be analysed and fixed + # appropriately. + if diff -r buildA/stage2 buildA_extended/stage2; then + echo "No differences found." + echo "has_diff=false" >> $GITHUB_OUTPUT + else + echo "Differences found!" + echo "has_diff=true" >> $GITHUB_OUTPUT + fi - # Perform a diff between the two builds - diff -r ../buildA/stage2 ../buildA_extended/stage2 || echo "Differences found!" - - tar -czf buildA.tar.gz ../buildA - tar -czf buildA_extended.tar.gz ../buildA_extended - +# Upload buildA and buildA_extended directories as an artifact (for debugging purposes) +# The artifacts contain the stage2 folder from both builds. The artifact are +# helpful to debug the reproducibility issue when this test fails. - name: Upload buildA artifact + if: steps.compare.outputs.has_diff == 'true' uses: actions/upload-artifact@v4 with: name: buildA - path: buildA.tar.gz + path: buildA - name: Upload buildA_extended artifact + if: steps.compare.outputs.has_diff == 'true' uses: actions/upload-artifact@v4 with: name: buildA_extended - path: buildA_extended.tar.gz + path: buildA_extended + +# Fail the job if differences were found between the builds + - name: Fail the job if there are differences + if: steps.compare.outputs.has_diff == 'true' + run: | + echo "Differences found between buildA and buildA_extended, Reproducibility check failed" + exit 1