Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .github/actions/binary-limit/binary-limit-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,22 @@ async function commentToPullRequest(github, context, comment) {
});
}

// `ci-binary.json` is uploaded by the base commit's own CI right after the binding
// build; `rspack-build.json` carries the same measurement but only lands once the
// ecosystem benchmark completes, so it is a fallback for commits predating that job.
async function fetchDataBySha(github, sha) {
const dir = `commits/${sha.slice(0, 2)}/${sha.slice(2)}`;
return (
(await fetchJson(github, `${dir}/ci-binary.json`)) ??
(await fetchJson(github, `${dir}/rspack-build.json`))
);
}

// Read via the authenticated Contents API rather than raw.githubusercontent.com:
// the CDN rate-limits anonymous requests per shared runner IP and 429s almost
// immediately, while the API uses the workflow token (5000 req/h) with octokit's
// built-in retry/throttling.
async function fetchDataBySha(github, sha) {
const path = `commits/${sha.slice(0, 2)}/${sha.slice(2)}/rspack-build.json`;
async function fetchJson(github, path) {
console.log(
'fetching',
`${DATA_REPO.owner}/${DATA_REPO.repo}:${path}`,
Expand Down
73 changes: 73 additions & 0 deletions .github/actions/binary-limit/upload-binary-size.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Uploads the ci-profile binary size of a main/v1.x commit to the benchmark data
// branch, so PRs can read a baseline minutes after the binding build instead of
// waiting for the ecosystem benchmark (release build + 40min bench) to finish.
const { execFileSync } = require('node:child_process');
const fs = require('node:fs');
const path = require('node:path');

const BINARY = 'crates/node_binding/rspack.linux-x64-gnu.node';
const DATA_DIR = '.benchmark-data';
const PUSH_RETRIES = 3;

const sha = process.env.GITHUB_SHA;
const token = process.env.PERF_DATA_TOKEN;
if (!sha || !token) {
throw new Error('GITHUB_SHA and PERF_DATA_TOKEN are required');
}

const size = fs.statSync(BINARY).size;
console.log(`Binary size of ${sha}: ${size}`);

const remote = `https://x-access-token:${token}@github.com/web-infra-dev/rspack-ecosystem-benchmark.git`;
const relativePath = path.join('commits', sha.slice(0, 2), sha.slice(2));

function git(...args) {
execFileSync('git', args, { cwd: DATA_DIR, stdio: 'inherit' });
}

// Self-hosted runners reuse workspaces, so a leftover clone from a previous run
// would make `git clone` fail.
fs.rmSync(DATA_DIR, { recursive: true, force: true });
execFileSync(
'git',
[
'clone',
'--branch',
'data',
'--single-branch',
'--depth',
'1',
remote,
DATA_DIR,
],
{ stdio: 'inherit' },
);
git('config', 'user.name', 'github-actions[bot]');
git(
'config',
'user.email',
'41898282+github-actions[bot]@users.noreply.github.com',
);

// The data branch is also written by the ecosystem benchmark upload, so a push can
// lose the race. Reset onto the new tip and re-apply rather than rebase: the file is
// commit-scoped, so re-writing it is always the correct resolution.
for (let attempt = 1; ; attempt++) {
fs.mkdirSync(path.join(DATA_DIR, relativePath), { recursive: true });
fs.writeFileSync(
path.join(DATA_DIR, relativePath, 'ci-binary.json'),
`${JSON.stringify({ size }, null, 2)}\n`,
);
git('add', path.join(relativePath, 'ci-binary.json'));
git('commit', '-m', `add ${sha.slice(0, 8)} ci binary size`);

try {
git('push');
break;
} catch (e) {
if (attempt === PUSH_RETRIES) throw e;
console.log(`Push rejected, retrying (${attempt}/${PUSH_RETRIES})`);
git('fetch', '--depth', '1', 'origin', 'data');
git('reset', '--hard', 'FETCH_HEAD');
}
}
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,29 @@ jobs:
workflow-file: rspack-ecosystem-ci-from-commit.yml
client-payload: '{"commitSHA":"${{ github.sha }}","updateComment":true,"repo":"web-infra-dev/rspack","suite":"-","suiteRefType":"precoded","suiteRef":"precoded","sourceRunId":"${{ github.run_id }}","sourceRepo":"web-infra-dev/rspack"}'

upload-binary-size:
name: Upload Binary Size
needs: [check-changed, build-linux]
if: ${{ needs.check-changed.outputs.code_changed == 'true' && github.event_name == 'push' && github.repository == 'web-infra-dev/rspack' }}
runs-on: ${{ fromJSON(vars.CI_LINUX_MINI_RUNNER || '"ubuntu-latest"') }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7

- name: Download binding artifact
uses: ./.github/actions/artifact/download
with:
name: bindings-x86_64-unknown-linux-gnu
path: crates/node_binding/

# Must mirror size-limit.yml: the uploaded size is the baseline PRs compare against.
- name: Strip binary
run: strip crates/node_binding/rspack.linux-x64-gnu.node

- name: Upload binary size
env:
PERF_DATA_TOKEN: ${{ secrets.PERF_DATA_TOKEN }}
run: node ./.github/actions/binary-limit/upload-binary-size.js

# TODO: enable it after self hosted runners are ready
# pkg-preview:
# name: Pkg Preview
Expand Down
Loading