mrdoob/three.js
5 workflows · maturity 50% · 4 patterns · GitHub ↗
Practices
✓ Matrix✓ Permissions✓ Security scan○ AI review○ Cache○ Concurrency○ Reusable workflows
Detected patterns
Security dimensions
Tools: github/codeql-action/analyze, github/codeql-action/autobuild, github/codeql-action/init
Workflows (5)
ci matrix perms .github/workflows/ci.yml
View raw YAML
name: CI
on:
pull_request:
paths-ignore:
- 'build/**'
- 'docs/**'
- 'files/**'
permissions:
contents: read
jobs:
test:
name: Lint, Unit, Unit addons, Circular dependencies & Examples testing
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: 24
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: === Lint testing ===
run: npm run lint
- name: === Unit testing ===
run: npm run test-unit
- name: === Unit addons testing ===
run: npm run test-unit-addons
- name: === Examples ready for release ===
run: npm run test-e2e-cov
e2e:
name: E2E testing
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
CI: [ 0, 1, 2, 3, 4 ]
env:
CI: ${{ matrix.CI }}
steps:
- name: Git checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: 24
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build-module
- name: === E2E testing ===
run: npm run test-e2e
- name: Upload output screenshots
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
if: always()
with:
name: Output screenshots-${{ matrix.os }}-${{ matrix.CI }}
path: test/e2e/output-screenshots
if-no-files-found: ignore
codeql-code-scanning matrix security .github/workflows/codeql-code-scanning.yml
View raw YAML
name: "CodeQL"
on:
push:
branches: [ "dev" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "dev" ]
schedule:
- cron: '29 23 * * 0'
workflow_dispatch:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql-config.yml
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@38697555549f1db7851b81482ff19f1fa5c4fedc # v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4
with:
category: "/language:${{matrix.language}}"
protected-folders perms .github/workflows/protected-folders.yml
View raw YAML
name: Protected Folders Check
on:
pull_request:
paths:
- 'build/**'
- 'docs/**'
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Check for protected folder changes
if: ${{ github.event.pull_request.author_association != 'OWNER' && github.event.pull_request.author_association != 'COLLABORATOR' }}
run: |
echo "::error::The 'build' and 'docs' folders are auto-generated and cannot be modified in PRs. Please remove these changes from your PR."
exit 1
read-size perms .github/workflows/read-size.yml
View raw YAML
name: Read size
on:
pull_request:
paths:
- 'src/**'
- 'package.json'
- 'utils/build/**'
# This workflow runs in a read-only environment. We can safely checkout
# the PR code here.
# Reference:
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
permissions:
contents: read
jobs:
read-size:
name: Tree-shaking
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: 24
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: === Test tree-shaking ===
run: npm run test-treeshake
- name: Read bundle sizes
id: read-size
run: |
WEBGL_FILESIZE=$(stat --format=%s build/three.module.min.js)
gzip -k build/three.module.min.js
WEBGL_FILESIZE_GZIP=$(stat --format=%s build/three.module.min.js.gz)
WEBGL_TREESHAKEN=$(stat --format=%s test/treeshake/index.bundle.min.js)
gzip -k test/treeshake/index.bundle.min.js
WEBGL_TREESHAKEN_GZIP=$(stat --format=%s test/treeshake/index.bundle.min.js.gz)
WEBGPU_FILESIZE=$(stat --format=%s build/three.webgpu.min.js)
gzip -k build/three.webgpu.min.js
WEBGPU_FILESIZE_GZIP=$(stat --format=%s build/three.webgpu.min.js.gz)
WEBGPU_TREESHAKEN=$(stat --format=%s test/treeshake/index.webgpu.bundle.min.js)
gzip -k test/treeshake/index.webgpu.bundle.min.js
WEBGPU_TREESHAKEN_GZIP=$(stat --format=%s test/treeshake/index.webgpu.bundle.min.js.gz)
WEBGPU_NODES_FILESIZE=$(stat --format=%s build/three.webgpu.nodes.min.js)
gzip -k build/three.webgpu.nodes.min.js
WEBGPU_NODES_FILESIZE_GZIP=$(stat --format=%s build/three.webgpu.nodes.min.js.gz)
WEBGPU_NODES_TREESHAKEN=$(stat --format=%s test/treeshake/index.webgpu.nodes.bundle.min.js)
gzip -k test/treeshake/index.webgpu.nodes.bundle.min.js
WEBGPU_NODES_TREESHAKEN_GZIP=$(stat --format=%s test/treeshake/index.webgpu.nodes.bundle.min.js.gz)
PR=${{ github.event.pull_request.number }}
# write the output in a json file to upload it as artifact
node -pe "JSON.stringify({ filesize: $WEBGL_FILESIZE, gzip: $WEBGL_FILESIZE_GZIP, treeshaken: $WEBGL_TREESHAKEN, treeshakenGzip: $WEBGL_TREESHAKEN_GZIP, filesize2: $WEBGPU_FILESIZE, gzip2: $WEBGPU_FILESIZE_GZIP, treeshaken2: $WEBGPU_TREESHAKEN, treeshakenGzip2: $WEBGPU_TREESHAKEN_GZIP, filesize3: $WEBGPU_NODES_FILESIZE, gzip3: $WEBGPU_NODES_FILESIZE_GZIP, treeshaken3: $WEBGPU_NODES_TREESHAKEN, treeshakenGzip3: $WEBGPU_NODES_TREESHAKEN_GZIP, pr: $PR })" > sizes.json
- name: Upload artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: sizes
path: sizes.json
report-size perms .github/workflows/report-size.yml
View raw YAML
name: Report size
on:
workflow_run:
workflows: ["Read size"]
types:
- completed
# This workflow needs to be run with "pull-requests: write" permissions to
# be able to comment on the pull request. We can't checkout the PR code
# in this workflow.
# Reference:
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
permissions:
pull-requests: write
jobs:
report-size:
name: Comment on PR
runs-on: ubuntu-latest
if: github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
steps:
- name: Log GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
# Using actions/download-artifact doesn't work here
# https://github.com/actions/download-artifact/issues/60
- name: Download artifact
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
id: download-artifact
with:
result-encoding: string
script: |
const fs = require('fs/promises');
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const matchArtifact = artifacts.data.artifacts.find((artifact) => artifact.name === 'sizes');
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
await fs.writeFile('sizes.zip', Buffer.from(download.data));
await exec.exec('unzip sizes.zip');
const json = await fs.readFile('sizes.json', 'utf8');
return json;
# This runs on the base branch of the PR, meaning "dev"
- name: Git checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: 24
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: === Test tree-shaking ===
run: npm run test-treeshake
- name: Read sizes
id: read-size
run: |
WEBGL_FILESIZE_BASE=$(stat --format=%s build/three.module.min.js)
gzip -k build/three.module.min.js
WEBGL_FILESIZE_BASE_GZIP=$(stat --format=%s build/three.module.min.js.gz)
WEBGL_TREESHAKEN_BASE=$(stat --format=%s test/treeshake/index.bundle.min.js)
gzip -k test/treeshake/index.bundle.min.js
WEBGL_TREESHAKEN_BASE_GZIP=$(stat --format=%s test/treeshake/index.bundle.min.js.gz)
WEBGPU_FILESIZE_BASE=$(stat --format=%s build/three.webgpu.min.js)
gzip -k build/three.webgpu.min.js
WEBGPU_FILESIZE_BASE_GZIP=$(stat --format=%s build/three.webgpu.min.js.gz)
WEBGPU_TREESHAKEN_BASE=$(stat --format=%s test/treeshake/index.webgpu.bundle.min.js)
gzip -k test/treeshake/index.webgpu.bundle.min.js
WEBGPU_TREESHAKEN_BASE_GZIP=$(stat --format=%s test/treeshake/index.webgpu.bundle.min.js.gz)
WEBGPU_NODES_FILESIZE_BASE=$(stat --format=%s build/three.webgpu.nodes.min.js)
gzip -k build/three.webgpu.nodes.min.js
WEBGPU_NODES_FILESIZE_BASE_GZIP=$(stat --format=%s build/three.webgpu.nodes.min.js.gz)
WEBGPU_NODES_TREESHAKEN_BASE=$(stat --format=%s test/treeshake/index.webgpu.nodes.bundle.min.js)
gzip -k test/treeshake/index.webgpu.nodes.bundle.min.js
WEBGPU_NODES_TREESHAKEN_BASE_GZIP=$(stat --format=%s test/treeshake/index.webgpu.nodes.bundle.min.js.gz)
# log to console
echo "WEBGL_FILESIZE_BASE=$WEBGL_FILESIZE_BASE"
echo "WEBGL_FILESIZE_BASE_GZIP=$WEBGL_FILESIZE_BASE_GZIP"
echo "WEBGL_TREESHAKEN_BASE=$WEBGL_TREESHAKEN_BASE"
echo "WEBGL_TREESHAKEN_BASE_GZIP=$WEBGL_TREESHAKEN_BASE_GZIP"
echo "WEBGL_FILESIZE_BASE=$WEBGL_FILESIZE_BASE" >> $GITHUB_OUTPUT
echo "WEBGL_FILESIZE_BASE_GZIP=$WEBGL_FILESIZE_BASE_GZIP" >> $GITHUB_OUTPUT
echo "WEBGL_TREESHAKEN_BASE=$WEBGL_TREESHAKEN_BASE" >> $GITHUB_OUTPUT
echo "WEBGL_TREESHAKEN_BASE_GZIP=$WEBGL_TREESHAKEN_BASE_GZIP" >> $GITHUB_OUTPUT
echo "WEBGPU_FILESIZE_BASE=$WEBGPU_FILESIZE_BASE"
echo "WEBGPU_FILESIZE_BASE_GZIP=$WEBGPU_FILESIZE_BASE_GZIP"
echo "WEBGPU_TREESHAKEN_BASE=$WEBGPU_TREESHAKEN_BASE"
echo "WEBGPU_TREESHAKEN_BASE_GZIP=$WEBGPU_TREESHAKEN_BASE_GZIP"
echo "WEBGPU_FILESIZE_BASE=$WEBGPU_FILESIZE_BASE" >> $GITHUB_OUTPUT
echo "WEBGPU_FILESIZE_BASE_GZIP=$WEBGPU_FILESIZE_BASE_GZIP" >> $GITHUB_OUTPUT
echo "WEBGPU_TREESHAKEN_BASE=$WEBGPU_TREESHAKEN_BASE" >> $GITHUB_OUTPUT
echo "WEBGPU_TREESHAKEN_BASE_GZIP=$WEBGPU_TREESHAKEN_BASE_GZIP" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_FILESIZE_BASE=$WEBGPU_NODES_FILESIZE_BASE"
echo "WEBGPU_NODES_FILESIZE_BASE_GZIP=$WEBGPU_NODES_FILESIZE_BASE_GZIP"
echo "WEBGPU_NODES_TREESHAKEN_BASE=$WEBGPU_NODES_TREESHAKEN_BASE"
echo "WEBGPU_NODES_TREESHAKEN_BASE_GZIP=$WEBGPU_NODES_TREESHAKEN_BASE_GZIP"
echo "WEBGPU_NODES_FILESIZE_BASE=$WEBGPU_NODES_FILESIZE_BASE" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_FILESIZE_BASE_GZIP=$WEBGPU_NODES_FILESIZE_BASE_GZIP" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_TREESHAKEN_BASE=$WEBGPU_NODES_TREESHAKEN_BASE" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_TREESHAKEN_BASE_GZIP=$WEBGPU_NODES_TREESHAKEN_BASE_GZIP" >> $GITHUB_OUTPUT
- name: Format sizes
id: format
# It's important these are passed as env variables.
# https://securitylab.github.com/research/github-actions-untrusted-input/
env:
WEBGL_FILESIZE: ${{ fromJSON(steps.download-artifact.outputs.result).filesize }}
WEBGL_FILESIZE_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).gzip }}
WEBGL_FILESIZE_BASE: ${{ steps.read-size.outputs.WEBGL_FILESIZE_BASE }}
WEBGL_FILESIZE_BASE_GZIP: ${{ steps.read-size.outputs.WEBGL_FILESIZE_BASE_GZIP }}
WEBGL_TREESHAKEN: ${{ fromJSON(steps.download-artifact.outputs.result).treeshaken }}
WEBGL_TREESHAKEN_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).treeshakenGzip }}
WEBGL_TREESHAKEN_BASE: ${{ steps.read-size.outputs.WEBGL_TREESHAKEN_BASE }}
WEBGL_TREESHAKEN_BASE_GZIP: ${{ steps.read-size.outputs.WEBGL_TREESHAKEN_BASE_GZIP }}
WEBGPU_FILESIZE: ${{ fromJSON(steps.download-artifact.outputs.result).filesize2 }}
WEBGPU_FILESIZE_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).gzip2 }}
WEBGPU_FILESIZE_BASE: ${{ steps.read-size.outputs.WEBGPU_FILESIZE_BASE }}
WEBGPU_FILESIZE_BASE_GZIP: ${{ steps.read-size.outputs.WEBGPU_FILESIZE_BASE_GZIP }}
WEBGPU_TREESHAKEN: ${{ fromJSON(steps.download-artifact.outputs.result).treeshaken2 }}
WEBGPU_TREESHAKEN_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).treeshakenGzip2 }}
WEBGPU_TREESHAKEN_BASE: ${{ steps.read-size.outputs.WEBGPU_TREESHAKEN_BASE }}
WEBGPU_TREESHAKEN_BASE_GZIP: ${{ steps.read-size.outputs.WEBGPU_TREESHAKEN_BASE_GZIP }}
WEBGPU_NODES_FILESIZE: ${{ fromJSON(steps.download-artifact.outputs.result).filesize3 }}
WEBGPU_NODES_FILESIZE_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).gzip3 }}
WEBGPU_NODES_FILESIZE_BASE: ${{ steps.read-size.outputs.WEBGPU_NODES_FILESIZE_BASE }}
WEBGPU_NODES_FILESIZE_BASE_GZIP: ${{ steps.read-size.outputs.WEBGPU_NODES_FILESIZE_BASE_GZIP }}
WEBGPU_NODES_TREESHAKEN: ${{ fromJSON(steps.download-artifact.outputs.result).treeshaken3 }}
WEBGPU_NODES_TREESHAKEN_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).treeshakenGzip3 }}
WEBGPU_NODES_TREESHAKEN_BASE: ${{ steps.read-size.outputs.WEBGPU_NODES_TREESHAKEN_BASE }}
WEBGPU_NODES_TREESHAKEN_BASE_GZIP: ${{ steps.read-size.outputs.WEBGPU_NODES_TREESHAKEN_BASE_GZIP }}
run: |
WEBGL_FILESIZE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_FILESIZE")
WEBGL_FILESIZE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_FILESIZE_GZIP")
WEBGL_FILESIZE_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_FILESIZE_BASE")
WEBGL_FILESIZE_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_FILESIZE_BASE_GZIP")
WEBGL_FILESIZE_DIFF=$(node ./test/treeshake/utils/format-diff.js "$WEBGL_FILESIZE" "$WEBGL_FILESIZE_BASE")
WEBGL_FILESIZE_DIFF_GZIP=$(node ./test/treeshake/utils/format-diff.js "$WEBGL_FILESIZE_GZIP" "$WEBGL_FILESIZE_BASE_GZIP")
WEBGL_TREESHAKEN_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_TREESHAKEN")
WEBGL_TREESHAKEN_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_TREESHAKEN_GZIP")
WEBGL_TREESHAKEN_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_TREESHAKEN_BASE")
WEBGL_TREESHAKEN_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_TREESHAKEN_BASE_GZIP")
WEBGL_TREESHAKEN_DIFF=$(node ./test/treeshake/utils/format-diff.js "$WEBGL_TREESHAKEN" "$WEBGL_TREESHAKEN_BASE")
WEBGL_TREESHAKEN_DIFF_GZIP=$(node ./test/treeshake/utils/format-diff.js "$WEBGL_TREESHAKEN_GZIP" "$WEBGL_TREESHAKEN_BASE_GZIP")
WEBGPU_FILESIZE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_FILESIZE")
WEBGPU_FILESIZE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_FILESIZE_GZIP")
WEBGPU_FILESIZE_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_FILESIZE_BASE")
WEBGPU_FILESIZE_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_FILESIZE_BASE_GZIP")
WEBGPU_FILESIZE_DIFF=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_FILESIZE" "$WEBGPU_FILESIZE_BASE")
WEBGPU_FILESIZE_DIFF_GZIP=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_FILESIZE_GZIP" "$WEBGPU_FILESIZE_BASE_GZIP")
WEBGPU_TREESHAKEN_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_TREESHAKEN")
WEBGPU_TREESHAKEN_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_TREESHAKEN_GZIP")
WEBGPU_TREESHAKEN_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_TREESHAKEN_BASE")
WEBGPU_TREESHAKEN_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_TREESHAKEN_BASE_GZIP")
WEBGPU_TREESHAKEN_DIFF=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_TREESHAKEN" "$WEBGPU_TREESHAKEN_BASE")
WEBGPU_TREESHAKEN_DIFF_GZIP=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_TREESHAKEN_GZIP" "$WEBGPU_TREESHAKEN_BASE_GZIP")
WEBGPU_NODES_FILESIZE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_NODES_FILESIZE")
WEBGPU_NODES_FILESIZE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_NODES_FILESIZE_GZIP")
WEBGPU_NODES_FILESIZE_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_NODES_FILESIZE_BASE")
WEBGPU_NODES_FILESIZE_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_NODES_FILESIZE_BASE_GZIP")
WEBGPU_NODES_FILESIZE_DIFF=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_NODES_FILESIZE" "$WEBGPU_NODES_FILESIZE_BASE")
WEBGPU_NODES_FILESIZE_DIFF_GZIP=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_NODES_FILESIZE_GZIP" "$WEBGPU_NODES_FILESIZE_BASE_GZIP")
WEBGPU_NODES_TREESHAKEN_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_NODES_TREESHAKEN")
WEBGPU_NODES_TREESHAKEN_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_NODES_TREESHAKEN_GZIP")
WEBGPU_NODES_TREESHAKEN_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_NODES_TREESHAKEN_BASE")
WEBGPU_NODES_TREESHAKEN_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGPU_NODES_TREESHAKEN_BASE_GZIP")
WEBGPU_NODES_TREESHAKEN_DIFF=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_NODES_TREESHAKEN" "$WEBGPU_NODES_TREESHAKEN_BASE")
WEBGPU_NODES_TREESHAKEN_DIFF_GZIP=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_NODES_TREESHAKEN_GZIP" "$WEBGPU_NODES_TREESHAKEN_BASE_GZIP")
echo "WEBGL_FILESIZE=$WEBGL_FILESIZE_FORM" >> $GITHUB_OUTPUT
echo "WEBGL_FILESIZE_GZIP=$WEBGL_FILESIZE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGL_FILESIZE_BASE=$WEBGL_FILESIZE_BASE_FORM" >> $GITHUB_OUTPUT
echo "WEBGL_FILESIZE_BASE_GZIP=$WEBGL_FILESIZE_BASE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGL_FILESIZE_DIFF=$WEBGL_FILESIZE_DIFF" >> $GITHUB_OUTPUT
echo "WEBGL_FILESIZE_DIFF_GZIP=$WEBGL_FILESIZE_DIFF_GZIP" >> $GITHUB_OUTPUT
echo "WEBGL_TREESHAKEN=$WEBGL_TREESHAKEN_FORM" >> $GITHUB_OUTPUT
echo "WEBGL_TREESHAKEN_GZIP=$WEBGL_TREESHAKEN_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGL_TREESHAKEN_BASE=$WEBGL_TREESHAKEN_BASE_FORM" >> $GITHUB_OUTPUT
echo "WEBGL_TREESHAKEN_BASE_GZIP=$WEBGL_TREESHAKEN_BASE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGL_TREESHAKEN_DIFF=$WEBGL_TREESHAKEN_DIFF" >> $GITHUB_OUTPUT
echo "WEBGL_TREESHAKEN_DIFF_GZIP=$WEBGL_TREESHAKEN_DIFF_GZIP" >> $GITHUB_OUTPUT
echo "WEBGPU_FILESIZE=$WEBGPU_FILESIZE_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_FILESIZE_GZIP=$WEBGPU_FILESIZE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_FILESIZE_BASE=$WEBGPU_FILESIZE_BASE_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_FILESIZE_BASE_GZIP=$WEBGPU_FILESIZE_BASE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_FILESIZE_DIFF=$WEBGPU_FILESIZE_DIFF" >> $GITHUB_OUTPUT
echo "WEBGPU_FILESIZE_DIFF_GZIP=$WEBGPU_FILESIZE_DIFF_GZIP" >> $GITHUB_OUTPUT
echo "WEBGPU_TREESHAKEN=$WEBGPU_TREESHAKEN_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_TREESHAKEN_GZIP=$WEBGPU_TREESHAKEN_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_TREESHAKEN_BASE=$WEBGPU_TREESHAKEN_BASE_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_TREESHAKEN_BASE_GZIP=$WEBGPU_TREESHAKEN_BASE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_TREESHAKEN_DIFF=$WEBGPU_TREESHAKEN_DIFF" >> $GITHUB_OUTPUT
echo "WEBGPU_TREESHAKEN_DIFF_GZIP=$WEBGPU_TREESHAKEN_DIFF_GZIP" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_FILESIZE=$WEBGPU_NODES_FILESIZE_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_FILESIZE_GZIP=$WEBGPU_NODES_FILESIZE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_FILESIZE_BASE=$WEBGPU_NODES_FILESIZE_BASE_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_FILESIZE_BASE_GZIP=$WEBGPU_NODES_FILESIZE_BASE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_FILESIZE_DIFF=$WEBGPU_NODES_FILESIZE_DIFF" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_FILESIZE_DIFF_GZIP=$WEBGPU_NODES_FILESIZE_DIFF_GZIP" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_TREESHAKEN=$WEBGPU_NODES_TREESHAKEN_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_TREESHAKEN_GZIP=$WEBGPU_NODES_TREESHAKEN_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_TREESHAKEN_BASE=$WEBGPU_NODES_TREESHAKEN_BASE_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_TREESHAKEN_BASE_GZIP=$WEBGPU_NODES_TREESHAKEN_BASE_GZIP_FORM" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_TREESHAKEN_DIFF=$WEBGPU_NODES_TREESHAKEN_DIFF" >> $GITHUB_OUTPUT
echo "WEBGPU_NODES_TREESHAKEN_DIFF_GZIP=$WEBGPU_NODES_TREESHAKEN_DIFF_GZIP" >> $GITHUB_OUTPUT
- name: Find existing comment
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4
id: find-comment
with:
issue-number: ${{ fromJSON(steps.download-artifact.outputs.result).pr }}
comment-author: 'github-actions[bot]'
body-includes: Bundle size
- name: Comment on PR
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5
with:
issue-number: ${{ fromJSON(steps.download-artifact.outputs.result).pr }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
edit-mode: replace
body: |
### 📦 Bundle size
_Full ESM build, minified and gzipped._
|| Before | After | Diff |
|:-:|:-:|:-:|:-:|
| WebGL | ${{ steps.format.outputs.WEBGL_FILESIZE_BASE }} <br> **${{ steps.format.outputs.WEBGL_FILESIZE_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGL_FILESIZE }} <br> **${{ steps.format.outputs.WEBGL_FILESIZE_GZIP }}** | ${{ steps.format.outputs.WEBGL_FILESIZE_DIFF }} <br> **${{ steps.format.outputs.WEBGL_FILESIZE_DIFF_GZIP }}** |
| WebGPU | ${{ steps.format.outputs.WEBGPU_FILESIZE_BASE }} <br> **${{ steps.format.outputs.WEBGPU_FILESIZE_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_FILESIZE }} <br> **${{ steps.format.outputs.WEBGPU_FILESIZE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_FILESIZE_DIFF }} <br> **${{ steps.format.outputs.WEBGPU_FILESIZE_DIFF_GZIP }}** |
| WebGPU Nodes | ${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_BASE }} <br> **${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_NODES_FILESIZE }} <br> **${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_DIFF }} <br> **${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_DIFF_GZIP }}** |
### 🌳 Bundle size after tree-shaking
_Minimal build including a renderer, camera, empty scene, and dependencies._
|| Before | After | Diff |
|:-:|:-:|:-:|:-:|
| WebGL | ${{ steps.format.outputs.WEBGL_TREESHAKEN_BASE }} <br> **${{ steps.format.outputs.WEBGL_TREESHAKEN_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGL_TREESHAKEN }} <br> **${{ steps.format.outputs.WEBGL_TREESHAKEN_GZIP }}** | ${{ steps.format.outputs.WEBGL_TREESHAKEN_DIFF }} <br> **${{ steps.format.outputs.WEBGL_TREESHAKEN_DIFF_GZIP }}** |
| WebGPU | ${{ steps.format.outputs.WEBGPU_TREESHAKEN_BASE }} <br> **${{ steps.format.outputs.WEBGPU_TREESHAKEN_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_TREESHAKEN }} <br> **${{ steps.format.outputs.WEBGPU_TREESHAKEN_GZIP }}** | ${{ steps.format.outputs.WEBGPU_TREESHAKEN_DIFF }} <br> **${{ steps.format.outputs.WEBGPU_TREESHAKEN_DIFF_GZIP }}** |
| WebGPU Nodes | ${{ steps.format.outputs.WEBGPU_NODES_TREESHAKEN_BASE }} <br> **${{ steps.format.outputs.WEBGPU_NODES_TREESHAKEN_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_NODES_TREESHAKEN }} <br> **${{ steps.format.outputs.WEBGPU_NODES_TREESHAKEN_GZIP }}** | ${{ steps.format.outputs.WEBGPU_NODES_TREESHAKEN_DIFF }} <br> **${{ steps.format.outputs.WEBGPU_NODES_TREESHAKEN_DIFF_GZIP }}** |