Skip to content
Open
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
5 changes: 5 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# actionlint config — registers labels that exist on our self-hosted runners
# but not on GH-hosted ones, so the linter stops flagging them as typos.
self-hosted-runner:
labels:
- incredibuild-runner
79 changes: 79 additions & 0 deletions .github/actions/ib-metrics/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: ib-metrics
description: |
Parse an ib_console monitor log and write a markdown summary to
$GITHUB_STEP_SUMMARY: task counts, local vs helper distribution,
parallelism factor, cache hit rate. Treats missing fields gracefully.

inputs:
log-path:
description: "Path to the ib_console log produced by ib-build"
required: true
label:
description: "Heading for the summary block"
required: false
default: "Incredibuild metrics"

runs:
using: composite
steps:
- name: Write summary
shell: bash
env:
LOG_PATH: ${{ inputs.log-path }}
LABEL: ${{ inputs.label }}
run: |
set -uo pipefail
if [[ ! -s "$LOG_PATH" ]]; then
{
echo "## $LABEL"
echo
echo "_no log captured at \`$LOG_PATH\`_"
} >> "$GITHUB_STEP_SUMMARY"
exit 0
fi

# Heuristic extraction. ib_console with monitor_enable="true" emits
# lines like:
# [task] helper N: clang -c ...
# [task] local : ld ...
# plus a final block:
# Total tasks: X
# Tasks executed locally: Y
# Tasks executed remotely: Z
# Parallel acceleration: K.K x
total_tasks=$(grep -Ei "Total tasks" "$LOG_PATH" | tail -1 | grep -oE '[0-9]+' | head -1 || true)
local_tasks=$(grep -Ei "(executed locally|local tasks)" "$LOG_PATH" | tail -1 | grep -oE '[0-9]+' | head -1 || true)
remote_tasks=$(grep -Ei "(executed remotely|remote tasks)" "$LOG_PATH" | tail -1 | grep -oE '[0-9]+' | head -1 || true)
accel=$(grep -Ei "(acceleration|speedup)" "$LOG_PATH" | tail -1 | grep -oE '[0-9]+(\.[0-9]+)?' | head -1 || true)
wall=$(grep -Ei "(wall.?time|build duration|total time)" "$LOG_PATH" | tail -1 || true)

# Fallback if the structured block isn't found: count placement lines.
if [[ -z "$total_tasks" ]]; then
local_tasks=$(grep -cE '\[(task|exec)\][^]]*local' "$LOG_PATH" || echo 0)
remote_tasks=$(grep -cE '\[(task|exec)\][^]]*(helper|remote)' "$LOG_PATH" || echo 0)
total_tasks=$(( local_tasks + remote_tasks ))
fi

cache_hits=$(grep -ciE "cache.?hit" "$LOG_PATH" || echo 0)
cache_miss=$(grep -ciE "cache.?miss" "$LOG_PATH" || echo 0)

{
echo "## $LABEL"
echo
echo "| metric | value |"
echo "| --- | --- |"
echo "| total tasks | ${total_tasks:-?} |"
echo "| local tasks | ${local_tasks:-?} |"
echo "| remote tasks | ${remote_tasks:-?} |"
if [[ -n "$accel" ]]; then echo "| parallel acceleration | ${accel}x |"; fi
if [[ -n "$wall" ]]; then echo "| wall time | \`$wall\` |"; fi
echo "| cache hits | $cache_hits |"
echo "| cache misses | $cache_miss |"
echo
echo "<details><summary>log tail (last 50 lines)</summary>"
echo
echo "\`\`\`"
tail -n 50 "$LOG_PATH"
echo "\`\`\`"
echo "</details>"
} >> "$GITHUB_STEP_SUMMARY"
114 changes: 114 additions & 0 deletions .github/workflows/incredibuild-compare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: incredibuild-compare

# Side-by-side acceleration benchmark on a vnext IB runner: builds the
# same Bun profile twice on the same runner, once with the IB ninja shim
# active and once with IB_CONSOLE_SKIP=1 (the shim recognizes this and
# falls back to plain ninja). Reports the wall-time delta.

on:
workflow_dispatch:
inputs:
bun_profile:
description: "Bun build profile to benchmark"
required: true
default: "ci-cpp-only"
type: choice
options:
- debug
- release
- ci-cpp-only
- ci-rust-only
- ci-release
iterations:
description: "Iterations per variant (median reported)"
required: false
default: "1"
type: string
clean_between:
description: "Wipe build dir between iterations (cold) vs reuse (warm)"
required: false
default: true
type: boolean

concurrency:
group: incredibuild-compare-${{ github.ref }}
cancel-in-progress: false

jobs:
benchmark:
runs-on: incredibuild-runner
timeout-minutes: 240
env:
BUN_PROFILE: ${{ inputs.bun_profile }}
ITERATIONS: ${{ inputs.iterations }}
CLEAN: ${{ inputs.clean_between }}

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Activate Bun-specific IB profile
run: cp .incredibuild/ib_profile.xml ib_profile.xml

- name: Warm dependencies once (excluded from timing)
run: |
set -euo pipefail
bun scripts/build.ts --profile="$BUN_PROFILE" --configure-only

- name: Stock builds (IB_CONSOLE_SKIP=1 disables the ninja shim)
id: stock
env:
IB_CONSOLE_SKIP: "1"
run: |
set -euo pipefail
times=/tmp/stock-times.txt
: > "$times"
for i in $(seq 1 "$ITERATIONS"); do
[[ "$CLEAN" == "true" ]] && rm -rf "build/$BUN_PROFILE"
t0=$(date +%s.%N)
bun scripts/build.ts --profile="$BUN_PROFILE"
t1=$(date +%s.%N)
dt=$(awk -v a="$t0" -v b="$t1" 'BEGIN{print b-a}')
echo "$dt" >> "$times"
echo "stock iter $i: ${dt}s" >&2
done
median=$(sort -n "$times" | awk 'NR==int(NR/2)+1')
echo "median=$median" >> "$GITHUB_OUTPUT"

- name: IB-accelerated builds (shim active)
id: ib
run: |
set -euo pipefail
times=/tmp/ib-times.txt
: > "$times"
for i in $(seq 1 "$ITERATIONS"); do
[[ "$CLEAN" == "true" ]] && rm -rf "build/$BUN_PROFILE"
t0=$(date +%s.%N)
bun scripts/build.ts --profile="$BUN_PROFILE"
t1=$(date +%s.%N)
dt=$(awk -v a="$t0" -v b="$t1" 'BEGIN{print b-a}')
echo "$dt" >> "$times"
echo "ib iter $i: ${dt}s" >&2
done
median=$(sort -n "$times" | awk 'NR==int(NR/2)+1')
echo "median=$median" >> "$GITHUB_OUTPUT"

- name: Report
run: |
stock=${{ steps.stock.outputs.median }}
ib=${{ steps.ib.outputs.median }}
speedup=$(awk -v s="$stock" -v i="$ib" 'BEGIN{ if (i>0) printf "%.2f", s/i; else print "n/a"}')
delta=$(awk -v s="$stock" -v i="$ib" 'BEGIN{printf "%.2f", s-i}')
{
echo "## Incredibuild speedup — $BUN_PROFILE"
echo
echo "| variant | median wall (s) |"
echo "| --- | --- |"
echo "| stock (IB_CONSOLE_SKIP=1) | $stock |"
echo "| ib-accelerated | $ib |"
echo
echo "**delta:** ${delta}s saved · **speedup:** ${speedup}×"
echo
echo "_(${ITERATIONS} iteration(s), clean-between=${CLEAN})_"
} >> "$GITHUB_STEP_SUMMARY"
133 changes: 133 additions & 0 deletions .github/workflows/incredibuild-linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
name: incredibuild-linux

# Build Bun on a vnext-processing-engine Incredibuild runner.
#
# The runner image (nscr.io/.../incredibuild-runner:latest, from
# Incredibuild-RND/vnext-processing-engine) already PATH-shims `ninja`,
# `cmake`, `cargo`, etc. to invoke `ib_console --standalone
# --build-cache-local-shared --build-cache-force --build-cache-basedir=$PWD`
# transparently. So we just need to:
# 1. Drop our Bun-specific profile at $PWD/ib_profile.xml (highest
# priority in ib_console's default profile load order).
# 2. Run `bun scripts/build.ts` normally — the shim does the rest.
#
# Two jobs:
# 1. validate-profile-xsd (ubuntu-latest) — runs on every push/PR.
# 2. ib-build (incredibuild-runner) — workflow_dispatch only.
on:
workflow_dispatch:
inputs:
bun_profile:
description: "Bun build profile"
required: true
default: "ci-cpp-only"
type: choice
options:
- debug
- release
- ci-cpp-only
- ci-rust-only
- ci-link-only
- ci-release
debug_shim:
description: "Set IB_ACCEL_DEBUG=1 so the shim logs every transformation"
required: false
default: false
type: boolean
push:
branches:
- "incredibuild/**"
pull_request:
paths:
- ".incredibuild/**"
- ".github/actions/ib-metrics/**"
- ".github/workflows/incredibuild-linux.yml"
- "scripts/build.ts"

concurrency:
group: incredibuild-linux-${{ github.ref }}
cancel-in-progress: true

jobs:
validate-profile-xsd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install xmllint + shellcheck
run: sudo apt-get update && sudo apt-get install -y libxml2-utils shellcheck
- name: Validate .incredibuild/ib_profile.xml
run: ./.incredibuild/validate.sh
- name: Shellcheck wrapper scripts
run: shellcheck .incredibuild/build.sh .incredibuild/validate.sh

ib-build:
needs: validate-profile-xsd
if: ${{ github.event_name == 'workflow_dispatch' }}
runs-on: incredibuild-runner
timeout-minutes: 120

env:
BUN_PROFILE: ${{ inputs.bun_profile || 'ci-cpp-only' }}
IB_ACCEL_DEBUG: ${{ inputs.debug_shim == true && '1' || '0' }}

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Activate Bun-specific IB profile
run: |
set -euo pipefail
# vnext runner's ninja shim wraps with `ib_console --standalone …`
# without --profile, so ib_console resolves via the default load
# order. $PWD/ib_profile.xml is the highest-priority slot.
cp .incredibuild/ib_profile.xml ib_profile.xml
xmllint --noout --schema .incredibuild/ib_profile.xsd ib_profile.xml
echo "[ib] profile active at $PWD/ib_profile.xml"

- name: Show effective IB env
run: |
echo "ib_console: $(command -v ib_console || echo 'not on PATH')"
ib_console --version 2>/dev/null || true
echo "ninja shim: $(command -v ninja)"
echo "IB_ACCEL_DIR=${IB_ACCEL_DIR:-}"
echo "IB_ACCEL_DEBUG=${IB_ACCEL_DEBUG:-}"

- name: Build Bun
id: build
run: |
set -o pipefail
log="${RUNNER_TEMP:-/tmp}/ib-build-${BUN_PROFILE}.log"
echo "log-path=$log" >> "$GITHUB_OUTPUT"
# The PATH shim does the ib_console wrapping for ninja transparently.
# We just need to invoke the normal Bun build entry point.
bun scripts/build.ts --profile="$BUN_PROFILE" 2>&1 | tee "$log"

- name: Acceleration metrics
if: always()
uses: ./.github/actions/ib-metrics
with:
log-path: ${{ steps.build.outputs.log-path }}
label: "Incredibuild — ${{ env.BUN_PROFILE }}"

- name: Upload IB build log
if: always()
uses: actions/upload-artifact@v4
with:
name: ib-log-${{ env.BUN_PROFILE }}
path: ${{ steps.build.outputs.log-path }}
if-no-files-found: ignore
retention-days: 14

- name: Upload build dir on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-failure-${{ env.BUN_PROFILE }}
path: |
build/**/CMakeFiles/CMakeOutput.log
build/**/CMakeFiles/CMakeError.log
build/**/build.ninja
build/**/*.log
if-no-files-found: ignore
retention-days: 7
Loading
Loading