| # This workflow checks if a PR commit has changed the size of a hello world Rust program. |
| # It downloads Rustc and compiles two versions of a stage0 compiler - one using the base commit |
| # of the PR, and one using the latest commit in the PR. |
| # If the size of the hello world program has changed, it posts a comment to the PR. |
| name: Check binary size |
| |
| on: |
| pull_request_target: |
| branches: |
| - master |
| |
| # Both the "measure" and "report" jobs need to know this. |
| env: |
| SIZE_DATA_DIR: sizes |
| |
| # Responsibility is divided between two jobs "measure" and "report", so that the |
| # job that builds (and potentnially runs) untrusted code does not have PR write |
| # permission, and vice-versa. |
| jobs: |
| measure: |
| name: Check binary size |
| strategy: |
| matrix: |
| platform: [ubuntu-latest, windows-latest] |
| runs-on: ${{ matrix.platform }} |
| permissions: |
| contents: read |
| env: |
| # This cannot be used as a context variable in the 'uses' key later. If it |
| # changes, update those steps too. |
| BACKTRACE_DIR: backtrace |
| RUSTC_DIR: rustc |
| TEST_MAIN_RS: foo.rs |
| BASE_COMMIT: ${{ github.event.pull_request.base.sha }} |
| HEAD_COMMIT: ${{ github.event.pull_request.head.sha }} |
| SIZE_DATA_FILE: size-${{ strategy.job-index }}.json |
| steps: |
| - name: Print info |
| shell: bash |
| run: | |
| echo "Current SHA: $HEAD_COMMIT" |
| echo "Base SHA: $BASE_COMMIT" |
| # Note: the backtrace source that's cloned here is NOT the version to be |
| # patched in to std. It's cloned here to access the Github action for |
| # building and measuring the test binary. |
| - name: Clone backtrace to access Github action |
| uses: actions/checkout@v3 |
| with: |
| path: ${{ env.BACKTRACE_DIR }} |
| - name: Clone Rustc |
| uses: actions/checkout@v3 |
| with: |
| repository: rust-lang/rust |
| path: ${{ env.RUSTC_DIR }} |
| - name: Set up std repository and backtrace submodule for size test |
| shell: bash |
| working-directory: ${{ env.RUSTC_DIR }} |
| env: |
| PR_SOURCE_REPO: ${{ github.event.pull_request.head.repo.full_name }} |
| run: | |
| # Bootstrap config |
| cat <<EOF > config.toml |
| [llvm] |
| download-ci-llvm = true |
| [rust] |
| incremental = false |
| EOF |
| |
| # Test program source |
| cat <<EOF > $TEST_MAIN_RS |
| fn main() { |
| panic!(); |
| } |
| EOF |
| |
| git submodule update --init library/backtrace |
| |
| cd library/backtrace |
| git remote add head-pr "https://github.com/$PR_SOURCE_REPO" |
| git fetch --all |
| - name: Build binary with base version of backtrace |
| uses: ./backtrace/.github/actions/build-with-patched-std |
| with: |
| backtrace-commit: ${{ env.BASE_COMMIT }} |
| main-rs: ${{ env.TEST_MAIN_RS }} |
| rustc-dir: ${{ env.RUSTC_DIR }} |
| id: size-reference |
| - name: Build binary with PR version of backtrace |
| uses: ./backtrace/.github/actions/build-with-patched-std |
| with: |
| backtrace-commit: ${{ env.HEAD_COMMIT }} |
| main-rs: ${{ env.TEST_MAIN_RS }} |
| rustc-dir: ${{ env.RUSTC_DIR }} |
| id: size-updated |
| # There is no built-in way to "collect" all the outputs of a set of jobs |
| # run with a matrix strategy. Subsequent jobs that have a "needs" |
| # dependency on this one will be run once, when the last matrix job is |
| # run. Appending data to a single file within a matrix is subject to race |
| # conditions. So we write the size data to files with distinct names |
| # generated from the job index. |
| - name: Write sizes to file |
| uses: actions/github-script@v6 |
| env: |
| SIZE_REFERENCE: ${{ steps.size-reference.outputs.test-binary-size }} |
| SIZE_UPDATED: ${{ steps.size-updated.outputs.test-binary-size }} |
| PLATFORM: ${{ matrix.platform }} |
| with: |
| script: | |
| const fs = require("fs"); |
| const path = require("path"); |
| |
| fs.mkdirSync(process.env.SIZE_DATA_DIR, {recursive: true}); |
| |
| const output_data = JSON.stringify({ |
| platform: process.env.PLATFORM, |
| reference: process.env.SIZE_REFERENCE, |
| updated: process.env.SIZE_UPDATED, |
| }); |
| |
| // The "wx" flag makes this fail if the file exists, which we want, |
| // because there should be no collisions. |
| fs.writeFileSync( |
| path.join(process.env.SIZE_DATA_DIR, process.env.SIZE_DATA_FILE), |
| output_data, |
| { flag: "wx" }, |
| ); |
| - name: Upload size data |
| uses: actions/upload-artifact@v3 |
| with: |
| name: size-files |
| path: ${{ env.SIZE_DATA_DIR }}/${{ env.SIZE_DATA_FILE }} |
| retention-days: 1 |
| if-no-files-found: error |
| report: |
| name: Report binary size changes |
| runs-on: ubuntu-latest |
| needs: measure |
| permissions: |
| pull-requests: write |
| steps: |
| # Clone backtrace to access Github composite actions to report size. |
| - uses: actions/checkout@v3 |
| - name: Download size data |
| uses: actions/download-artifact@v3 |
| with: |
| name: size-files |
| path: ${{ env.SIZE_DATA_DIR }} |
| - name: Analyze and report size changes |
| uses: ./.github/actions/report-code-size-changes |
| with: |
| data-directory: ${{ env.SIZE_DATA_DIR }} |