refactor: extract computeRenderTransform; move LD hit-test to model #15702
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: Push | |
| on: | |
| push: | |
| branches: | |
| - '*' | |
| tags: | |
| - '*' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| check_commit_message: | |
| name: Check Commit Message | |
| runs-on: ubuntu-latest | |
| outputs: | |
| skip_jobs: ${{ steps.check_message.outputs.skip_jobs }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Check commit message | |
| id: check_message | |
| env: | |
| COMMIT_MSG: ${{ github.event.head_commit.message }} | |
| run: | | |
| # Use env variable for safe expansion of special characters like quotes. | |
| if [[ "$COMMIT_MSG" == *"[update docs only]"* ]]; then | |
| echo "skip_jobs=true" >> $GITHUB_OUTPUT | |
| echo "Commit message contains [update docs only], skipping regular push jobs" | |
| else | |
| echo "skip_jobs=false" >> $GITHUB_OUTPUT | |
| echo "Running regular push jobs" | |
| fi | |
| test: | |
| name: Test and typecheck | |
| needs: check_commit_message | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - run: sudo apt-get -y install tabix | |
| - name: Install vg | |
| # vg ≥ 1.59.0 is required by tools/graph-truth-extractor and the | |
| # auditConcordance.test.ts Phase 5 CI suite. Without it those tests | |
| # silently skip; with it they enforce vg-find concordance on every | |
| # push. See agent-docs/GRAPH_PLAN.md. | |
| run: | | |
| curl -L -o /tmp/vg https://github.com/vgteam/vg/releases/download/v1.59.0/vg | |
| chmod +x /tmp/vg | |
| sudo mv /tmp/vg /usr/local/bin/vg | |
| vg version | head -1 | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| workspaces: tools/gfa-to-tabix | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| cache: 'pnpm' | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| - name: Test codebase | |
| id: tests | |
| run: pnpm test-ci | |
| continue-on-error: true | |
| - name: Configure AWS credentials | |
| if: steps.tests.outcome == 'failure' | |
| uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: us-east-1 | |
| - name: Upload jest image snapshot diffs to S3 | |
| if: steps.tests.outcome == 'failure' | |
| run: | | |
| SNAPSHOTS_DIR="products/jbrowse-web/src/tests/__image_snapshots__/__diff_output__" | |
| S3_PATH="s3://jbrowse.org/demos/imagediff/${{ github.run_id }}" | |
| if ls ${SNAPSHOTS_DIR}/*.png 1> /dev/null 2>&1; then | |
| echo "Uploading jest image snapshot diffs to S3..." | |
| aws s3 cp ${SNAPSHOTS_DIR}/ ${S3_PATH}/ --recursive --exclude "*" --include "*.png" | |
| echo "" | |
| echo "============================================" | |
| echo "JEST SNAPSHOT DIFF IMAGES UPLOADED TO S3" | |
| echo "============================================" | |
| for file in ${SNAPSHOTS_DIR}/*.png; do | |
| filename=$(basename "$file") | |
| echo "https://jbrowse.org/demos/imagediff/${{ github.run_id }}/${filename}" | |
| done | |
| echo "============================================" | |
| else | |
| echo "No jest snapshot diff files found" | |
| fi | |
| - name: Fail if tests failed | |
| if: steps.tests.outcome == 'failure' | |
| run: exit 1 | |
| - name: Upload coverage | |
| uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 | |
| - name: Typecheck codebase | |
| run: pnpm typecheck | |
| lint: | |
| name: Lint | |
| needs: check_commit_message | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| cache: 'pnpm' | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| - name: Check @jbrowse/core exports are up-to-date | |
| run: | | |
| node packages/core/scripts/generateExports.mjs | |
| if ! git diff --quiet packages/core/package.json; then | |
| echo "Error: @jbrowse/core exports are out of date!" | |
| echo "Run 'node packages/core/scripts/generateExports.mjs' and commit the changes." | |
| git diff packages/core/package.json | |
| exit 1 | |
| fi | |
| - name: Lint codebase | |
| run: pnpm lint | |
| check_shaders: | |
| name: Check shaders up to date | |
| needs: check_commit_message | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| cache: 'pnpm' | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| - name: Install glslangValidator | |
| run: sudo apt-get install -y glslang-tools | |
| - name: Regenerate shaders | |
| run: NAGA= pnpm gen:shaders | |
| - name: Check generated files are up to date | |
| run: | | |
| if ! git diff --quiet -- '**/*.generated.ts'; then | |
| echo "Error: shader generated files are out of date." | |
| echo "Run 'pnpm gen:shaders' and commit the changes." | |
| git diff -- '**/*.generated.ts' | |
| exit 1 | |
| fi | |
| format: | |
| name: Format | |
| needs: check_commit_message | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| cache: 'pnpm' | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| - name: Check codebase format | |
| run: pnpm prettier --check . | |
| spellcheck: | |
| name: Spell check | |
| needs: check_commit_message | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Check spelling | |
| uses: crate-ci/typos@7c572958218557a3272c2d6719629443b5cc26fd # v1.45.2 | |
| build_and_pack_artifacts: | |
| name: Build and pack artifacts | |
| needs: check_commit_message | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get -y install tabix libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev xvfb | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| cache: 'pnpm' | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| - name: Pack artifacts for component tests | |
| run: node --experimental-strip-types scripts/pack.ts | |
| - name: Test build | |
| run: BUILT_TESTS=1 pnpm built-test-ci | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: us-east-1 | |
| - name: Install Chrome for Puppeteer | |
| run: npx puppeteer browsers install chrome | |
| - name: Run browser tests with Puppeteer | |
| id: browser-tests | |
| run: node --experimental-strip-types browser-tests/runner.ts | |
| working-directory: products/jbrowse-web | |
| continue-on-error: true | |
| - name: Run auth browser tests with Puppeteer | |
| id: auth-browser-tests | |
| run: node --experimental-strip-types browser-tests/runner.ts --auth | |
| working-directory: products/jbrowse-web | |
| continue-on-error: true | |
| - name: Run WebGL backend browser tests | |
| id: webgl-browser-tests | |
| run: | |
| node --experimental-strip-types browser-tests/runner.ts | |
| --backend=webgl | |
| working-directory: products/jbrowse-web | |
| continue-on-error: true | |
| - name: Upload snapshot diffs to S3 | |
| if: | |
| steps.browser-tests.outcome == 'failure' || | |
| steps.auth-browser-tests.outcome == 'failure' || | |
| steps.webgl-browser-tests.outcome == 'failure' | |
| run: | | |
| SNAPSHOTS_DIR="products/jbrowse-web/browser-tests/__snapshots__" | |
| S3_PATH="s3://jbrowse.org/demos/imagediff/${{ github.run_id }}" | |
| FOUND_DIFFS=false | |
| for dir in "${SNAPSHOTS_DIR}" "${SNAPSHOTS_DIR}/webgl"; do | |
| if [ -d "$dir" ] && ls ${dir}/*.diff*.png 1> /dev/null 2>&1; then | |
| FOUND_DIFFS=true | |
| SUBDIR=$(basename "$dir") | |
| echo "Uploading snapshot diffs from ${dir} to S3..." | |
| aws s3 cp ${dir}/ ${S3_PATH}/${SUBDIR}/ --recursive --exclude "*" --include "*.diff*.png" | |
| echo "" | |
| echo "============================================" | |
| echo "SNAPSHOT DIFF IMAGES: ${dir}" | |
| echo "============================================" | |
| for file in ${dir}/*.diff*.png; do | |
| filename=$(basename "$file") | |
| echo "https://jbrowse.org/demos/imagediff/${{ github.run_id }}/${SUBDIR}/${filename}" | |
| done | |
| echo "============================================" | |
| fi | |
| done | |
| if [ "$FOUND_DIFFS" = false ]; then | |
| echo "No snapshot diff files found" | |
| fi | |
| - name: Fail if browser tests failed | |
| if: | |
| steps.browser-tests.outcome == 'failure' || | |
| steps.auth-browser-tests.outcome == 'failure' || | |
| steps.webgl-browser-tests.outcome == 'failure' | |
| run: exit 1 | |
| - name: Upload packed artifacts for component tests | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: packed-artifacts | |
| path: component_tests/*/packed/ | |
| retention-days: 1 | |
| deploy: | |
| name: Build and deploy jbrowse-web to S3 | |
| needs: check_commit_message | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| cache: 'pnpm' | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| - name: Validate branch/tag name for S3 path safety | |
| env: | |
| REF_NAME: ${{ github.ref_name }} | |
| run: | | |
| if ! [[ "$REF_NAME" =~ ^[a-zA-Z0-9_.\-]+$ ]]; then | |
| echo "Error: Invalid ref name '$REF_NAME'" | |
| echo "Ref names must contain only alphanumeric characters, hyphens, underscores, and periods" | |
| exit 1 | |
| fi | |
| echo "Ref name validated: $REF_NAME" | |
| echo "REF_NAME=$REF_NAME" >> "$GITHUB_ENV" | |
| - name: Build jbrowse-web | |
| run: | | |
| cd products/jbrowse-web/ | |
| NODE_OPTIONS='--max-old-space-size=6500' pnpm build | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: us-east-1 | |
| - name: Deploy to S3 | |
| run: | | |
| cd products/jbrowse-web/build | |
| zip -r "jbrowse-web-${REF_NAME}.zip" . | |
| cp test_data/config.json config.json | |
| aws s3 sync --delete . s3://jbrowse.org/code/jb2/${REF_NAME} | |
| aws cloudfront create-invalidation --distribution-id E13LGELJOT4GQO --paths "/code/jb2/${REF_NAME}/*" | |
| - name: Build LGV storybook | |
| run: pnpm storybook:build | |
| working-directory: products/jbrowse-react-linear-genome-view | |
| - name: Deploy LGV storybook | |
| if: | |
| github.ref == 'refs/heads/main' || startsWith(github.ref, | |
| 'refs/tags/') | |
| run: | | |
| aws s3 sync --delete storybook-static s3://jbrowse.org/storybook/lgv/${REF_NAME} | |
| aws cloudfront create-invalidation --distribution-id E13LGELJOT4GQO --paths "/storybook/lgv/${REF_NAME}/*" | |
| working-directory: products/jbrowse-react-linear-genome-view | |
| - name: Build React App storybook | |
| run: pnpm storybook:build | |
| working-directory: products/jbrowse-react-app | |
| - name: Deploy React App storybook | |
| if: | |
| github.ref == 'refs/heads/main' || startsWith(github.ref, | |
| 'refs/tags/') | |
| run: | | |
| aws s3 sync --delete storybook-static s3://jbrowse.org/storybook/app/${REF_NAME} | |
| aws cloudfront create-invalidation --distribution-id E13LGELJOT4GQO --paths "/storybook/app/${REF_NAME}/*" | |
| working-directory: products/jbrowse-react-app | |
| - name: Build CGV storybook | |
| run: pnpm storybook:build | |
| working-directory: products/jbrowse-react-circular-genome-view | |
| - name: Deploy CGV storybook | |
| if: | |
| github.ref == 'refs/heads/main' || startsWith(github.ref, | |
| 'refs/tags/') | |
| run: | | |
| aws s3 sync --delete storybook-static s3://jbrowse.org/storybook/cgv/${REF_NAME} | |
| aws cloudfront create-invalidation --distribution-id E13LGELJOT4GQO --paths "/storybook/cgv/${REF_NAME}/*" | |
| working-directory: products/jbrowse-react-circular-genome-view | |
| # Conditionally run the buildwebsite job | |
| buildwebsite: | |
| name: Build website | |
| needs: check_commit_message | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| cache: 'pnpm' | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| working-directory: website | |
| - name: Build website | |
| run: | | |
| cd website/ | |
| pnpm build | |
| mkdir testing | |
| mv build testing/jb2 | |
| - name: Check website links | |
| uses: untitaker/hyperlink@fb5bb9c5011a3d143a54b4b30aedc30ec5bc0f89 # 0.2.0 | |
| with: | |
| args: website/testing/ --check-anchors | |
| # Separate job for component_tests with no permissions. | |
| # These tests install npm packages without a yarn.lock, so untrusted | |
| # dependencies could potentially run malicious code. By isolating this | |
| # in a job with `permissions: {}`, we ensure that even if a rogue | |
| # dependency executes, it has no GitHub token access and cannot push | |
| # code, create issues/PRs, access secrets, or call GitHub APIs. | |
| component_tests: | |
| name: Test embedded components | |
| needs: [check_commit_message, build_and_pack_artifacts] | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| - name: Download packed artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: packed-artifacts | |
| path: component_tests/ | |
| - name: Test embedded components | |
| run: | | |
| for dir in component_tests/lgv-vite component_tests/cgv-vite component_tests/app-vite; do | |
| echo "Testing $dir" | |
| (cd $dir && yarn install && yarn e2e) | |
| done | |
| # Test CLI on Node 18 to ensure compatibility with older Node versions. | |
| # This job has no permissions since it installs npm packages without a lockfile. | |
| test_cli_compat: | |
| name: Test CLI on Node 18 | |
| needs: [check_commit_message, build_and_pack_artifacts] | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '18' | |
| - name: Download packed artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: packed-artifacts | |
| path: component_tests/ | |
| - name: Test CLI on Node 18 | |
| run: | | |
| cd component_tests/cli-node18 | |
| yarn install | |
| yarn testcli | |
| # Test @jbrowse/img to ensure the jb2export CLI works. | |
| # Requires Node ~24 for module.registerHooks API. | |
| # This job has no permissions since it installs npm packages without a lockfile. | |
| test_jbrowse_img: | |
| name: Test @jbrowse/img | |
| needs: [check_commit_message, build_and_pack_artifacts] | |
| if: needs.check_commit_message.outputs.skip_jobs != 'true' | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '24' | |
| - name: Download packed artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: packed-artifacts | |
| path: component_tests/ | |
| - name: Test @jbrowse/img | |
| run: | | |
| cd component_tests/jbrowse-img | |
| yarn install | |
| yarn testimg | |
| windows_electron_e2e: | |
| name: Windows Electron E2E Tests | |
| needs: [check_commit_message, test, lint, format, build_and_pack_artifacts] | |
| if: | |
| needs.check_commit_message.outputs.skip_jobs != 'true' && github.ref == | |
| 'refs/heads/main' | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '22' | |
| cache: 'pnpm' | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| - name: Build and test Electron on Windows | |
| run: pnpm test:e2e:ci:win | |
| working-directory: products/jbrowse-desktop | |
| env: | |
| NO_MINIMIZE: true |