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
345 changes: 2 additions & 343 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,108 +22,6 @@ env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

jobs:
client:
strategy:
matrix:
os:
- "ubuntu-latest"
- "windows-2025-vs2026"
- "macos-latest"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
with:
# Need full history to determine version number.
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: 24.x
cache: "npm"
cache-dependency-path: |
package-lock.json
# uv required for javascript tests
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: false
# go needed for fake_gcs_server used by the javascript tests
- name: Setup go
uses: actions/setup-go@v6
with:
go-version: "stable"
cache: false
- run: npm ci
- run: npm run format:fix
- name: Check for dirty working directory
run: git diff --exit-code
- run: npm run lint:check
- name: Typecheck with TypeScript
run: npm run typecheck
- name: Build client bundles
run: |
build_info="{'tag':'$(git describe --always --tags)', 'url':'https://github.com/google/neuroglancer/commit/$(git rev-parse HEAD)', 'timestamp':'$(date)'}"
npm run build -- --no-typecheck --no-lint --define NEUROGLANCER_BUILD_INFO="${build_info}"
echo $build_info > ./dist/client/version.json
shell: bash
- name: Build Python client bundles
run: npm run build-python -- --no-typecheck --no-lint
- run: npm run build-package
- name: Run JavaScript tests (including WebGL)
run: npm test
if: ${{ runner.os != 'macOS' }}
- name: Run JavaScript tests (excluding WebGL)
run: npm test -- --project node
if: ${{ runner.os == 'macOS' }}
- name: Run JavaScript benchmarks
run: npm run benchmark
- name: Upload NPM package as artifact
uses: actions/upload-artifact@v7
with:
name: npm-package
path: dist/package
if: ${{ runner.os == 'Linux' }}
- name: Upload client as artifact
uses: actions/upload-artifact@v7
with:
name: client
path: dist/client
if: ${{ runner.os == 'Linux' }}
- name: Upload Python client static as artifact
uses: actions/upload-artifact@v7
with:
name: python-client-static
path: python/neuroglancer/static/client
if: ${{ runner.os == 'Linux' }}
example-project-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
with:
version: 10
- uses: actions/setup-node@v6
with:
node-version: 24.x
cache: "pnpm"
cache-dependency-path: |
examples/**/pnpm-lock.yaml
- uses: actions/setup-node@v6
with:
node-version: 24.x
cache: "npm"
cache-dependency-path: |
package-lock.json
- run: npm ci
- run: npm run example-project-test -- --reporter=html
- name: Upload report and built clients
uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
name: example-project-test-results
path: |
playwright-report/
examples/*/*/dist/

# Builds Python package and runs Python tests
#
# On ubuntu-latest, this also runs browser-based tests. On Mac OS and
Expand All @@ -137,8 +35,6 @@ jobs:
- "3.13"
os:
- "ubuntu-latest"
- "windows-2025-vs2026"
- "macos-latest"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
Expand All @@ -163,246 +59,9 @@ jobs:
run: uvx nox -s test -- --skip-browser-tests
if: ${{ runner.os != 'Linux' }}
- name: Run python tests (include browser tests)
run: uvx nox -s test_xvfb -- --browser firefox
timeout-minutes: 3
run: uvx nox -s test_xvfb -- --browser firefox --timeout=120
if: ${{ runner.os == 'Linux' }}
# Verify that editable install works
- name: Test in editable form
run: uvx nox -s test_editable

python-build-package:
strategy:
matrix:
include:
- os: "ubuntu-latest"
cibw_build: "*"
wheel_identifier: "linux"
- os: "windows-2025-vs2026"
cibw_build: "*"
wheel_identifier: "windows"
- os: "macos-14"
cibw_build: "*_x86_64"
wheel_identifier: "macos_x86_64"
- os: "macos-14"
cibw_build: "*_arm64"
wheel_identifier: "macos_arm64"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
with:
# Need full history to determine version number.
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: 24.x
cache: "npm"
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: false
version: "0.11.6"
- name: Get uv cache dir
id: uv-cache
run: |
echo "dir=$(uv cache dir)" >> "$GITHUB_OUTPUT"
- run: npm ci
- run: |
build_info="{'tag':'$(git describe --always --tags)', 'url':'https://github.com/google/neuroglancer/commit/$(git rev-parse HEAD)', 'timestamp':'$(date)'}"
npm run build-python -- --no-typecheck --no-lint --define NEUROGLANCER_BUILD_INFO="${build_info}"
shell: bash
- name: Check for dirty working directory
run: git diff --exit-code
- name: Build Python source distribution (sdist)
run: uv build --sdist
if: ${{ runner.os == 'Linux' }}
- name: Build Python wheels
run: uvx nox -s cibuildwheel
env:
# On Linux, share uv cache with manylinux docker containers
CIBW_ENVIRONMENT_LINUX: UV_CACHE_DIR=/host${{ steps.uv-cache.outputs.dir }}
CIBW_BEFORE_ALL_LINUX: /project/python/build_tools/cibuildwheel_linux_cache_setup.sh /host${{ steps.uv-cache.outputs.dir }}
CIBW_BUILD: ${{ matrix.cibw_build }}
# cryptography>=49 dropped macOS x86_64 wheels (48.x shipped universal2),
# forcing a source build that can't cross-compile openssl on the arm64
# runner. CIBW_TEST_ENVIRONMENT_MACOS injects UV_CONSTRAINT into the
# cibuildwheel test subprocess (where uv pip install resolves deps),
# capping the transitive cryptography version for x86_64 test installs only.
CIBW_TEST_ENVIRONMENT_MACOS: ${{ matrix.wheel_identifier == 'macos_x86_64' && format('UV_CONSTRAINT={0}/python/build_tools/macos-x86_64-test-constraints.txt', github.workspace) || '' }}
- name: Upload wheels as artifacts
uses: actions/upload-artifact@v7
with:
name: python-wheels-${{ matrix.wheel_identifier }}
path: |
dist/*.whl
dist/*.tar.gz

docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: false
- name: Setup Graphviz
uses: ts-graphviz/setup-graphviz@b1de5da23ed0a6d14e0aeee8ed52fdd87af2363c # v2.0.2
with:
macos-skip-brew-update: "true"
- name: Build docs
run: uvx nox -s docs
- name: Upload docs as artifact
uses: actions/upload-artifact@v7
with:
name: docs
path: |
dist/docs

publish:
# Only publish package on push to tag.
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
runs-on: ubuntu-latest
needs:
- "client"
- "python-build-package"
steps:
- uses: actions/checkout@v6
- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version: 24.x
registry-url: "https://registry.npmjs.org"
- uses: actions/download-artifact@v8
with:
pattern: python-wheels-*
path: dist
merge-multiple: true
- uses: actions/download-artifact@v8
with:
name: npm-package
path: npm-package
- name: Publish to PyPI (main server)
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
user: __token__
password: ${{ secrets.pypi_token }}
- name: Publish to NPM registry
run: npm publish
working-directory: npm-package
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

deploy:
# Only deploy on push to master branch.
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
runs-on: ubuntu-latest
needs:
- "client"
- "docs"
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "24.18.0"
- uses: actions/download-artifact@v8
with:
name: client
path: dist/client
- uses: actions/download-artifact@v8
with:
name: python-client-static
path: python/neuroglancer/static/client
- name: Publish client to Firebase hosting
uses: FirebaseExtended/action-hosting-deploy@500ac625ca2dd40cbd15f7659af953801858032a # v0.11.0
with:
firebaseServiceAccount: "${{ secrets.FIREBASE_HOSTING_SERVICE_ACCOUNT_KEY }}"
projectId: neuroglancer-demo
channelId: live
target: app
- uses: actions/download-artifact@v8
with:
name: docs
path: dist/docs
- name: Publish docs to Firebase hosting
uses: FirebaseExtended/action-hosting-deploy@500ac625ca2dd40cbd15f7659af953801858032a # v0.11.0
with:
firebaseServiceAccount: "${{ secrets.FIREBASE_HOSTING_SERVICE_ACCOUNT_KEY }}"
projectId: neuroglancer-demo
channelId: live
target: docs
- name: Prepare App Engine deployment
run: |
mkdir appengine-deploy
mkdir appengine-deploy/public
mkdir appengine-deploy/public/python
cp -r dist/client/* appengine-deploy/public/
cp -r python/neuroglancer/static/client/* appengine-deploy/public/python/
cat > appengine-deploy/public/fafb.html <<EOF
<html>
<head><title>neuroglancer</title></head>
<body>
Redirecting to https://fafb-dot-neuroglancer-demo.appspot.com
<script>
window.location.href = "https://fafb-dot-neuroglancer-demo.appspot.com/" + (window.location.search || "") + (window.location.hash || "");
</script>
</body>
</html>
EOF
cat > appengine-deploy/app.yaml <<EOF
runtime: python312
automatic_scaling:
max_instances: 20
handlers:
- url: /(.+)
static_files: public/\1
upload: public/(.*)

- url: /
static_files: public/index.html
upload: public/index.html
EOF
shell: bash
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093"
with:
credentials_json: "${{ secrets.FIREBASE_HOSTING_SERVICE_ACCOUNT_KEY }}"
- id: "deploy-appengine"
name: "Deploy to App Engine"
uses: "google-github-actions/deploy-appengine@54d5fc7167ec790eb0233905e3cef384221b4619"
with:
working_directory: "appengine-deploy"
deliverables: "app.yaml"
project_id: "neuroglancer-demo"
promote: true
- name: Cleanup old App Engine versions
run: |
gcloud app versions list --format="value(version.id)" --sort-by="~version.createTime" --project neuroglancer-demo | grep '^[0-9]\{8\}t[0-9]\{6\}$' | tail -n +6 | xargs -r gcloud app versions delete --quiet --project neuroglancer-demo
shell: bash

ngauth:
strategy:
matrix:
os:
- ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Setup go
uses: actions/setup-go@v6
with:
go-version-file: ngauth_server/go.mod
cache-dependency-path: ngauth_server/go.sum
- run: go build .
working-directory: ngauth_server
wasm:
# Ensures that .wasm files are reproducible.
strategy:
matrix:
os:
- ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- run: ./src/mesh/draco/build.sh
- run: ./src/sliceview/compresso/build.sh
- run: ./src/sliceview/png/build.sh
- run: ./src/sliceview/jxl/build.sh
# Check that there are no differences.
- run: git diff --exit-code
Loading
Loading