Benchmark #506
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Benchmark | |
on: | |
issue_comment: | |
types: [created] | |
workflow_dispatch: | |
inputs: | |
compare-base: | |
description: 'Branch name to compare against' | |
type: string | |
default: b12.1.1 | |
required: true | |
notify: | |
description: 'Notify Slack channel' | |
type: boolean | |
default: true | |
required: true | |
schedule: | |
- cron: '0 0 * * *' # Run daily at midnight UTC | |
- cron: '0 1 * * *' # Run daily at 01:00 UTC | |
env: | |
NX_NO_CLOUD: true | |
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} | |
NX_BRANCH: ${{ github.ref }} | |
BRANCH_NAME: ${{ github.head_ref || github.ref_name }} | |
jobs: | |
# Check permissions for issue_comment events | |
check-permissions: | |
runs-on: ubuntu-latest | |
outputs: | |
allowed: ${{ steps.check.outputs.allowed }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Check user permissions | |
id: check | |
uses: ./external/ag-shared/github/actions/check-issue-comment-permissions | |
with: | |
command: '/benchmarks' | |
benchmark: | |
runs-on: macos-benchmark | |
permissions: | |
pull-requests: write | |
needs: check-permissions | |
# Only run if permissions check passed (success) or was skipped (for non-issue_comment events) | |
if: | | |
needs.check-permissions.result == 'success' && ( | |
github.event_name == 'workflow_dispatch' || | |
github.event_name == 'schedule' || | |
(github.event_name == 'issue_comment' && needs.check-permissions.outputs.allowed == 'true') | |
) | |
env: | |
AG_SKIP_NATIVE_DEP_VERSION_CHECK: 1 | |
JOB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
AG_BENCHMARK_SOFT_FAIL: 'true' | |
steps: | |
- name: Notify start | |
id: notify-start | |
uses: actions/github-script@v7 | |
continue-on-error: true | |
if: github.event_name == 'issue_comment' | |
with: | |
result-encoding: string | |
script: | | |
const { data: comment } = await github.rest.issues.createComment({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `⏱️ ${process.env.JOB_URL}` | |
}) | |
return comment.id; | |
- id: 'get-branch' | |
run: | | |
if [[ "${{ github.event_name }}" == "issue_comment" ]] ; then | |
# For PR comments, get the branch from the PR | |
echo "branch=$(gh pr view $PR_NO --repo $REPO --json headRefName --jq '.headRefName')" >> $GITHUB_OUTPUT | |
echo "base=$(gh pr view $PR_NO --repo $REPO --json baseRefName --jq '.baseRefName')" >> $GITHUB_OUTPUT | |
elif [[ "${{ github.event_name }}" == "schedule" && "${{ github.event.schedule }}" == "0 1 * * *" ]] ; then | |
# For secondary scheduled runs, compare against b11.3.1 | |
echo "branch=latest" >> $GITHUB_OUTPUT | |
echo "base=b11.3.1" >> $GITHUB_OUTPUT | |
elif [[ "${{ github.event_name }}" == "schedule" ]] ; then | |
# For scheduled runs, get the most recent branch matching 'b' followed by semver (e.g. b1.2.3) | |
release=$(git ls-remote --heads origin 'b[0-9]*\.[0-9]*\.[0-9]*' | sort -t '/' -k 2 -V | tail -n 1 | sed 's/.*refs\/heads\///') | |
echo "branch=latest" >> $GITHUB_OUTPUT | |
echo "base=$release" >> $GITHUB_OUTPUT | |
else | |
# For manual workflow dispatch, use the current branch | |
echo "branch=${{ github.ref_name }}" >> $GITHUB_OUTPUT | |
echo "base=${{ inputs.compare-base }}" >> $GITHUB_OUTPUT | |
fi | |
env: | |
REPO: ${{ github.repository }} | |
PR_NO: ${{ github.event.issue.number }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ steps.get-branch.outputs.branch }} | |
fetch-depth: 0 | |
- name: Fetch Refs | |
run: | | |
set -x | |
if [[ "${{ steps.get-branch.outputs.base }}" =~ "^@" ]] ; then | |
base=$(git rev-parse --abbrev-ref ${{ steps.get-branch.outputs.base }}) | |
else | |
base=origin/${{ steps.get-branch.outputs.base }} | |
fi | |
git fetch --unshallow origin $base || echo "Not a shallow ref?" | |
# Preemptively fail if merge-base is not found. | |
mergeBase=$(git merge-base HEAD $base || echo "failed") | |
if [[ ${mergeBase} == "failed" ]] ; then | |
# Debugging | |
git log -n 1 --decorate HEAD | |
git log -n 20 --decorate $base | |
# Allow for a few minutes for debugging | |
sleep 600 | |
fi | |
- name: Notify Progress | |
uses: actions/github-script@v7 | |
continue-on-error: true | |
if: github.event_name == 'issue_comment' | |
with: | |
script: | | |
github.rest.issues.updateComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
comment_id: ${{ steps.notify-start.outputs.result }}, | |
body: `⏱️ ${process.env.JOB_URL} (running setup...)` | |
}) | |
- name: Setup | |
id: setup | |
uses: ./.github/actions/setup-nx | |
with: | |
cache_mode: rw | |
base_ref: ${{ steps.get-branch.outputs.base }} | |
fetch_base: skip | |
- name: Notify Progress | |
uses: actions/github-script@v7 | |
continue-on-error: true | |
if: github.event_name == 'issue_comment' | |
with: | |
script: | | |
github.rest.issues.updateComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
comment_id: ${{ steps.notify-start.outputs.result }}, | |
body: `⏱️ ${process.env.JOB_URL} (running benchmarks...)` | |
}) | |
- name: nx benchmark | |
id: benchmark-table | |
if: github.event_name == 'issue_comment' && (steps.setup.outcome == 'success' || steps.setup.outcome == 'skipped') | |
run: | | |
./tools/benchmark/compare-latest.sh origin/${{ steps.get-branch.outputs.base }} | |
echo "report<<EOF" >> $GITHUB_OUTPUT | |
cat ./reports/benchmark.log >> $GITHUB_OUTPUT | |
echo "EOF" >> $GITHUB_OUTPUT | |
- name: nx benchmark | |
id: benchmark-json | |
if: github.event_name != 'issue_comment' && (steps.setup.outcome == 'success' || steps.setup.outcome == 'skipped') | |
run: | | |
./tools/benchmark/compare-latest.sh -j origin/${{ steps.get-branch.outputs.base }} | |
- name: Notify Success | |
uses: actions/github-script@v7 | |
continue-on-error: true | |
if: success() && github.event_name == 'issue_comment' | |
env: | |
CONTENT: ${{ steps.benchmark-table.outputs.report }} | |
with: | |
script: | | |
const body = `✅ ${process.env.JOB_URL} | |
\`\`\` | |
${process.env.CONTENT} | |
\`\`\``; | |
github.rest.issues.updateComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
comment_id: ${{ steps.notify-start.outputs.result }}, | |
body, | |
}) | |
- name: Notify Failure | |
uses: actions/github-script@v7 | |
continue-on-error: true | |
if: failure() && github.event_name == 'issue_comment' | |
with: | |
script: | | |
const body = `❌ ${process.env.JOB_URL}` | |
github.rest.issues.updateComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
comment_id: ${{ steps.notify-start.outputs.result }}, | |
body, | |
}) | |
- name: Slack Notification | |
if: success() && (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.notify == true)) | |
continue-on-error: true | |
env: | |
SLACK_CHANNEL: '#charts-performance' | |
SLACK_ICON: 'https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_192.png' | |
SLACK_USERNAME: 'ag-charts CI' | |
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
SLACK_COLOR: ${{ steps.benchmark-json.outputs.status != 'failure' && 'success' || 'failure' }} | |
run: | | |
node ./tools/benchmark/format-slack-message.js > ./reports/benchmark-slack.json | |
curl -X POST -H 'Content-type: application/json' ${{ secrets.SLACK_WEBHOOK }} --data @./reports/benchmark-slack.json | |
- name: Slack Notification | |
if: failure() && (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.notify == true)) | |
continue-on-error: true | |
env: | |
SLACK_CHANNEL: '#charts-performance' | |
SLACK_ICON: 'https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_192.png' | |
SLACK_USERNAME: 'ag-charts CI' | |
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
SLACK_COLOR: ${{ steps.benchmark-json.outputs.status != 'failure' && 'success' || 'failure' }} | |
run: | | |
cat <<EOF > ./reports/benchmark-slack.json | |
{ | |
"channel": "${SLACK_CHANNEL}", | |
"username": "${SLACK_USERNAME}", | |
"icon_url": "${SLACK_ICON}", | |
"blocks": [ | |
{ | |
"type": "section", | |
"text": { | |
"type": "mrkdwn", | |
"text": "❌ Benchmark failed: [Run #${{ github.run_id }}](${JOB_URL})" | |
} | |
} | |
] | |
} | |
EOF | |
curl -X POST -H 'Content-type: application/json' ${{ secrets.SLACK_WEBHOOK }} --data @./reports/benchmark-slack.json | |
- name: Perist benchmark results | |
if: always() | |
uses: actions/upload-artifact@v4 | |
with: | |
name: benchmark-results | |
path: | | |
packages/ag-charts-website/src/content/docs/benchmarks/_examples/summary/* |