Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
9e2e0ad
Add initial GHA CI files
camdecoster Mar 27, 2026
5b66092
Include GH workflow files for Biome
camdecoster Mar 27, 2026
b1a4a81
Copy fonts into .github directory
camdecoster Mar 27, 2026
54a8c78
Copy scripts to .github
camdecoster Mar 27, 2026
7e77383
Update numpy
camdecoster Mar 27, 2026
b93ee8f
Cancel ongoing CI runs on new commit
camdecoster Mar 27, 2026
639310b
Create missing directory
camdecoster Mar 27, 2026
544e51e
Switch to headless mode for Karma, use variable for Node version
camdecoster Mar 30, 2026
d44372c
Switch Karma to new headless mode
camdecoster Mar 30, 2026
0127606
Switch back to xvfb
camdecoster Mar 30, 2026
d02406a
Create test_images folder in script
camdecoster Mar 30, 2026
ad2e1cb
Update directory structure for baseline diff tests
camdecoster Mar 30, 2026
6089d18
Linting/formatting
camdecoster Mar 30, 2026
96977ba
Add diff directory during diff tests
camdecoster Mar 30, 2026
b4c5abe
Refactor script
camdecoster Mar 31, 2026
68b1d48
Refactor script to use multiple threads, update syntax
camdecoster Mar 31, 2026
acbe728
Use same disallow list for making images, checking diffs
camdecoster Mar 31, 2026
c7fdf6c
Add debugging to broken test
camdecoster Mar 31, 2026
1dbe7a6
Update xvfb config
camdecoster Mar 31, 2026
9eaec28
Call xvfb directly
camdecoster Mar 31, 2026
402196a
Update Karma config
camdecoster Mar 31, 2026
92367ef
Remove debugging code
camdecoster Mar 31, 2026
f59d26d
Revert mock and add new mock
camdecoster Mar 31, 2026
cae3dd8
Move image env set up to composite action, update Kaleido
camdecoster Apr 1, 2026
7363314
Update uv setup
camdecoster Apr 1, 2026
c97b57e
Handle missing baseline image
camdecoster Apr 1, 2026
e536a7e
Run make-exports step with uv python
camdecoster Apr 1, 2026
fea595e
Linting/formatting
camdecoster Apr 1, 2026
fe6aa6d
Update make exports script
camdecoster Apr 1, 2026
ca7d608
Remove old noCI workflow
camdecoster Apr 2, 2026
10a2f10
Merge remote-tracking branch 'origin/master' into cam/7732/migrate-fr…
camdecoster Apr 2, 2026
7e5c299
Update triggers
camdecoster Apr 2, 2026
a19cdf9
Avoid uploading baseline images when image diffs detected
camdecoster Apr 2, 2026
7cee3f5
Add new baseline image
camdecoster Apr 2, 2026
584756e
Upgrade pixelmatch
camdecoster Apr 3, 2026
7a9e5aa
Don't run pixelmatch if image dims don't match
camdecoster Apr 3, 2026
802d7e0
Revert "Upgrade pixelmatch"
camdecoster Apr 3, 2026
67b94dd
Merge remote-tracking branch 'origin/master' into cam/7732/migrate-fr…
camdecoster Apr 3, 2026
519976c
Upgrade pixelmatch
camdecoster Apr 3, 2026
9df935b
Switch compare script to ESM
camdecoster Apr 3, 2026
dbf7305
Update file references
camdecoster Apr 3, 2026
d9fe89e
Don't use Node 21 syntax
camdecoster Apr 3, 2026
807ca94
Remove obsolete calls
camdecoster Apr 3, 2026
6c8e23e
Add debug code
camdecoster Apr 3, 2026
e7199ea
Update virtual webgl mock list
camdecoster Apr 3, 2026
5c0c683
Add second list for image comparisons
camdecoster Apr 3, 2026
e407f9a
Update baseline images
camdecoster Apr 3, 2026
809745d
Use baseline images from test-baselines
camdecoster Apr 3, 2026
fa2743e
Generate virtual-webgl specific images
camdecoster Apr 3, 2026
64fa1a8
Update more baseline images
camdecoster Apr 3, 2026
78c77fd
Add one more baseline image
camdecoster Apr 3, 2026
f5a3e4e
Remove mock prefix
camdecoster Apr 3, 2026
6bd8bbc
Remove more mock prefixes
camdecoster Apr 3, 2026
33660f9
Update baseline images
camdecoster Apr 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 13 additions & 0 deletions .github/actions/run-xvfb/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: 'Run with Xvfb'
description: 'Run a command under Xvfb with a preconfigured screen size'

inputs:
run:
description: 'Command to execute'
required: true

runs:
using: 'composite'
steps:
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x1024x24" ${{ inputs.run }}
shell: bash
19 changes: 19 additions & 0 deletions .github/actions/setup-chrome/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: 'Setup Chrome'
description: 'Install Chrome and set CHROME_BIN environment variable'

inputs:
chrome-version:
description: 'Chrome version to install'
default: '135.0.7049.95'

runs:
using: 'composite'
steps:
- uses: browser-actions/setup-chrome@v2
id: setup-chrome
with:
chrome-version: ${{ inputs.chrome-version }}

- name: Set Chrome binary path
run: echo "CHROME_BIN=${{ steps.setup-chrome.outputs.chrome-path }}" >> $GITHUB_ENV
shell: bash
26 changes: 26 additions & 0 deletions .github/actions/setup-image-env/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: 'Setup Image Environment'
description: 'Setup Python, uv, and install Kaleido/plotly with required fonts'

inputs:
python-version:
description: 'Python version to use'
default: '3.12'
uv-version:
description: 'uv version to use'
default: '0.11.2'

runs:
using: 'composite'
steps:
- uses: actions/setup-python@v6
with:
python-version: ${{ inputs.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: ${{ inputs.uv-version }}

- name: Install Kaleido, plotly.io and required fonts
run: .github/scripts/env_image.sh
shell: bash
26 changes: 26 additions & 0 deletions .github/actions/setup-workspace/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: 'Setup Workspace'
description: 'Setup Node.js, install dependencies, and download build artifacts'

inputs:
node-version:
description: 'Node.js version to use'
default: '18.20.4'

runs:
using: 'composite'
steps:
- uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'

- name: Install dependencies
run: npm ci
shell: bash
env:
NODE_OPTIONS: '--max-old-space-size=4096'

- uses: actions/download-artifact@v8
with:
name: build-output
path: .
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
6 changes: 6 additions & 0 deletions .github/scripts/env_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
export NODE_OPTIONS='--max-old-space-size=4096' && \
echo "node version: $(node --version)" && \
echo "npm version: $(npm --version)" && \
npm ci && \
npm ls --prod --all
19 changes: 19 additions & 0 deletions .github/scripts/env_image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh
set -e
# install required fonts
sudo apt-get install fonts-liberation2 fonts-open-sans fonts-noto-cjk fonts-noto-color-emoji

# install additional fonts (committed in .github/fonts/)
sudo cp -r .github/fonts/ /usr/share/
sudo apt install fontconfig
sudo fc-cache -f

# install Kaleido & Plotly
uv pip install --system kaleido==1.2 plotly==6.6.0 --no-progress

# install numpy i.e. to convert arrays to typed arrays
uv pip install --system numpy==2.4.3

# verify version of python and versions of installed python packages
python --version
uv pip freeze --system
20 changes: 20 additions & 0 deletions .github/scripts/split_files.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node

// Replacement for `circleci tests split`
// Reads lines from stdin and emits only those where index % SHARD_TOTAL == SHARD_INDEX
// Environment variables SHARD_INDEX and SHARD_TOTAL must be set.

import { readFileSync } from 'fs';

const lines = readFileSync('/dev/stdin', 'utf8').trim().split('\n').filter(Boolean);
const index = parseInt(process.env.SHARD_INDEX);
const total = parseInt(process.env.SHARD_TOTAL);

if (isNaN(index) || isNaN(total) || total <= 0) {
console.error('SHARD_INDEX and SHARD_TOTAL environment variables must be set to valid integers');
process.exit(1);
}

lines.forEach((line, i) => {
if (i % total === index) console.log(line);
});
154 changes: 154 additions & 0 deletions .github/scripts/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/bin/bash

# GitHub Actions version of .circleci/test.sh
# Replaces `circleci tests split` with split_files.mjs

set +e
set +o pipefail

ROOT=$(dirname $0)/../..
SPLIT="$ROOT/.github/scripts/split_files.mjs"
EXIT_STATE=0
MAX_AUTO_RETRY=0

log () {
echo -e "\n$1"
}

# inspired by https://unix.stackexchange.com/a/82602
retry () {
local n=1

until [ $n -ge $MAX_AUTO_RETRY ]; do
"$@" --failFast && break
log "run $n of $MAX_AUTO_RETRY failed, trying again ..."
n=$[$n+1]
done

if [ $n -eq $MAX_AUTO_RETRY ]; then
log "one last time, w/o failing fast"
"$@" && n=0
fi

if [ $n -eq $MAX_AUTO_RETRY ]; then
log "all $n runs failed, moving on."
EXIT_STATE=1
fi
}

# Ensure output directories exist (not present in fresh GHA checkout)
mkdir -p build/test_images

case $1 in

no-gl-jasmine)
SUITE=$(ls -1 $ROOT/test/jasmine/tests/* | sort | node "$SPLIT")
MAX_AUTO_RETRY=2
retry npm run test-jasmine -- $SUITE --skip-tags=gl,noCI,flaky || EXIT_STATE=$?

exit $EXIT_STATE
;;

webgl-jasmine)
SHARDS=($(node $ROOT/tasks/shard_jasmine_tests.js --limit=5 --tag=gl | node "$SPLIT"))
for s in ${SHARDS[@]}; do
MAX_AUTO_RETRY=2
retry npm run test-jasmine -- "$s" --tags=gl --skip-tags=noCI --doNotFailOnEmptyTestSuite
done

exit $EXIT_STATE
;;

virtual-webgl-jasmine)
SHARDS=($(node $ROOT/tasks/shard_jasmine_tests.js --limit=5 --tag=gl | node "$SPLIT"))
for s in ${SHARDS[@]}; do
MAX_AUTO_RETRY=2
retry ./node_modules/karma/bin/karma start test/jasmine/karma.conf.js --virtualWebgl --tags=gl --skip-tags=noCI,noVirtualWebgl --doNotFailOnEmptyTestSuite -- "$s"
done

exit $EXIT_STATE
;;

flaky-no-gl-jasmine)
SHARDS=($(node $ROOT/tasks/shard_jasmine_tests.js --limit=1 --tag=flaky | node "$SPLIT"))

for s in ${SHARDS[@]}; do
MAX_AUTO_RETRY=5
retry npm run test-jasmine -- "$s" --tags=flaky --skip-tags=noCI
done

exit $EXIT_STATE
;;

bundle-jasmine)
npm run test-bundle || EXIT_STATE=$?
exit $EXIT_STATE
;;

mathjax-firefox)
./node_modules/karma/bin/karma start test/jasmine/karma.conf.js --FF --bundleTest=mathjax --nowatch || EXIT_STATE=$?
exit $EXIT_STATE
;;

mathjax-firefox)
./node_modules/karma/bin/karma start test/jasmine/karma.conf.js --FF --bundleTest=mathjax --nowatch &&
./node_modules/karma/bin/karma start test/jasmine/karma.conf.js --FF --bundleTest=mathjax --mathjax3 --nowatch &&
./node_modules/karma/bin/karma start test/jasmine/karma.conf.js --FF --bundleTest=mathjax_config --mathjax3 --nowatch &&
./node_modules/karma/bin/karma start test/jasmine/karma.conf.js --FF --bundleTest=mathjax_config --nowatch || EXIT_STATE=$?
exit $EXIT_STATE
;;

make-baselines-virtual-webgl)
SUITE=$({\
find $ROOT/test/image/mocks/gl* -type f -printf "%f\n"; \
find $ROOT/test/image/mocks/map* -type f -printf "%f\n"; \
} | sed 's/\.json$//1' | sort | node "$SPLIT")
python test/image/make_baseline.py virtual-webgl $SUITE || EXIT_STATE=$?
exit $EXIT_STATE
;;

make-baselines-mathjax3)
MATHJAX3_MOCKS=$(jq -r '.compare_mathjax3 | join(" ")' test/image/compare_pixels_collections.json)
python test/image/make_baseline.py mathjax3 $MATHJAX3_MOCKS || EXIT_STATE=$?
exit $EXIT_STATE
;;

make-baselines-b64)
SUITE=$(find $ROOT/test/image/mocks/ -type f -printf "%f\n" | sed 's/\.json$//1' | sort | node "$SPLIT")
python test/image/make_baseline.py b64 $SUITE || EXIT_STATE=$?
exit $EXIT_STATE
;;

make-baselines)
SUITE=$(find $ROOT/test/image/mocks/ -type f -printf "%f\n" | sed 's/\.json$//1' | sort | node "$SPLIT")
python test/image/make_baseline.py $SUITE || EXIT_STATE=$?
exit $EXIT_STATE
;;

make-exports)
python test/image/make_exports.py || EXIT_STATE=$?
exit $EXIT_STATE
;;

test-image)
node test/image/compare_pixels_test.mjs || EXIT_STATE=$?
exit $EXIT_STATE
;;

test-image-mathjax3)
node test/image/compare_pixels_test.mjs mathjax3 || EXIT_STATE=$?
exit $EXIT_STATE
;;

test-image-virtual-webgl)
node test/image/compare_pixels_test.mjs virtual-webgl || EXIT_STATE=$?
exit $EXIT_STATE
;;

source-syntax)
npm run lint || EXIT_STATE=$?
npm run test-syntax || EXIT_STATE=$?
exit $EXIT_STATE
;;

esac
Loading
Loading