|
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 and stores the created toolchains |
| 3 | +# This workflow also runs on branches named reproducible |
| 4 | + |
| 5 | +name: Reproducibility check |
2 | 6 |
|
3 | 7 | on: |
4 | 8 | push: |
5 | | - branches: |
6 | | - - master |
7 | | - pull_request: |
8 | 9 | branches: |
9 | 10 | - master |
10 | 11 | - reproducible |
11 | 12 |
|
12 | 13 | jobs: |
13 | 14 | build_and_compare: |
14 | | - runs-on: ubuntu-latest |
| 15 | + runs-on: ubuntu-24.04 |
| 16 | + |
| 17 | + strategy: |
| 18 | + matrix: |
| 19 | + build_dir: [buildA, buildA_extended] |
15 | 20 |
|
16 | 21 | steps: |
17 | 22 | - 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 |
| 23 | + uses: actions/checkout@v4 |
24 | 24 |
|
25 | | - - name: Build and store buildA binaries |
| 25 | +# Build the two toolchains for comparision |
| 26 | + - name: Build and store ${{ matrix.build_dir }} binaries |
26 | 27 | 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 |
| 28 | + mkdir ../${{ matrix.build_dir }} |
| 29 | + cp -r "$(pwd)" ../${{ matrix.build_dir }} |
| 30 | + pushd ../${{ matrix.build_dir }} |
39 | 31 |
|
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)) |
| 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. |
46 | 36 | $SOURCE_DIR/configure --set rust.channel=nightly |
| 37 | +
|
| 38 | + # Build rust till stage 2 |
47 | 39 | $SOURCE_DIR/x.py build --stage 2 -j$(($(nproc)*2/3)) |
| 40 | +
|
| 41 | + # Remove copy of source directory to save space. |
48 | 42 | rm -rf $SOURCE_DIR |
49 | | - STAGE2_DIR=`find build -name stage2` |
| 43 | +
|
| 44 | + # Find stage 2 artifacts directory |
| 45 | + STAGE2_DIR=$(find build -name stage2) |
| 46 | +
|
| 47 | + # Save stage 2 directory contents before we delete build |
50 | 48 | cp -r "$STAGE2_DIR" . |
51 | | - echo "Contents stage 2 dir : `ls stage2`" |
| 49 | + echo "Contents stage 2 dir : $(ls stage2)" |
| 50 | +
|
| 51 | + # Remove build directory to save space |
52 | 52 | rm -rf build |
53 | 53 | popd |
54 | 54 |
|
55 | | - - name: Compare builds and archive artifacts |
| 55 | +# Compare the two builds |
| 56 | + - name: Compare builds |
| 57 | + id: compare |
56 | 58 | run: | |
57 | 59 | # Ensure the directories exist |
58 | 60 | if [[ ! -d "../buildA" || ! -d "../buildA_extended" ]]; then |
59 | 61 | echo "Error: Build directories not found!" |
60 | 62 | exit 1 |
61 | 63 | fi |
62 | 64 |
|
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 |
| 65 | + # Perform a recursive diff between the stage2 directories of both builds |
| 66 | + # If there are differences, record the result so we can upload artifacts and then fail later |
| 67 | + # The binaries should be identical, so the cause of difference should be analysed and fixed |
| 68 | + # appropriately. |
| 69 | + if diff -r ../buildA/stage2 ../buildA_extended/stage2; then |
| 70 | + echo "No differences found." |
| 71 | + echo "has_diff=false" >> $GITHUB_OUTPUT |
| 72 | + else |
| 73 | + echo "Differences found!" |
| 74 | + echo "has_diff=true" >> $GITHUB_OUTPUT |
| 75 | + fi |
68 | 76 |
|
| 77 | +# Upload buildA directory as an artifact (for debugging purposes) |
69 | 78 | - name: Upload buildA artifact |
| 79 | + if: steps.compare.outputs.has_diff == 'true' |
70 | 80 | uses: actions/upload-artifact@v4 |
71 | 81 | with: |
72 | 82 | name: buildA |
73 | | - path: buildA.tar.gz |
| 83 | + path: ../buildA |
74 | 84 |
|
| 85 | +# Upload buildA_extended directory as an artifact (for debugging purposes) |
75 | 86 | - name: Upload buildA_extended artifact |
| 87 | + if: steps.compare.outputs.has_diff == 'true' |
76 | 88 | uses: actions/upload-artifact@v4 |
77 | 89 | with: |
78 | 90 | name: buildA_extended |
79 | | - path: buildA_extended.tar.gz |
| 91 | + path: ../buildA_extended |
| 92 | + |
| 93 | +# Fail the job if differences were found between the builds |
| 94 | + - name: Fail the job if there are differences |
| 95 | + if: steps.compare.outputs.has_diff == 'true' |
| 96 | + run: | |
| 97 | + echo "Differences found between buildA and buildA_extended, Reproducibility check failed" |
| 98 | + exit 1 |
0 commit comments