Skip to content
Open
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
50 changes: 0 additions & 50 deletions .github/actions/percy-exec/action.yml

This file was deleted.

25 changes: 25 additions & 0 deletions .github/workflows/nitpix-approve.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: nitpix approve

# Handles `/nitpix approve` comments on PRs: records the approved snapshot
# hashes on the nitpix-baselines branch and flips the `nitpix/visual` commit
# status to success — without re-running the test matrix. Only users with
# write access can approve.

on:
issue_comment:
types: [created]

permissions:
contents: write
pull-requests: write
statuses: write

jobs:
approve:
name: Approve visual changes
runs-on: ubuntu-latest
if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/nitpix')
steps:
- uses: plotly/nitpix/approve@main # TODO: pin to @v1 once released

Check warning on line 23 in .github/workflows/nitpix-approve.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGq-lkMKz-IngxBX&open=AZ84FGq-lkMKz-IngxBX&pullRequest=3873

Check failure on line 23 in .github/workflows/nitpix-approve.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use full commit SHA hash for this dependency.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGq-lkMKz-IngxBW&open=AZ84FGq-lkMKz-IngxBW&pullRequest=3873
with:
baseline-branch: nitpix-baselines
43 changes: 43 additions & 0 deletions .github/workflows/nitpix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: nitpix

# Visual diffing (replaces Percy). Runs in the base-repo context via
# workflow_run so it has a full-privilege token even for fork and Dependabot
# PRs (which get a read-only token in "Dash Testing" itself).
#
# - PR-triggered test runs: diff the uploaded nitpix-snapshots-* artifacts
# against baselines/<base-branch>/ on the nitpix-baselines orphan branch,
# post/update the review comment and the `nitpix/visual` commit status.
# Approve visual changes by commenting `/nitpix approve` on the PR
# (see nitpix-approve.yml).
# - push-triggered test runs (dev/master): promote that run's snapshots to
# the branch's baselines.
#
# SECURITY: never check out or execute PR code in this workflow — it runs
# with write permissions for all PRs. nitpix only handles PNG artifacts.

on:
workflow_run:
workflows: ["Dash Testing"]
types: [completed]

permissions:
contents: write # push to the nitpix-baselines branch
pull-requests: write # the review comment
statuses: write # the nitpix/visual check

concurrency:
group: nitpix-${{ github.event.workflow_run.head_sha }}
cancel-in-progress: true

jobs:
visual-review:
name: Visual Review
runs-on: ubuntu-latest
if: |
github.event.workflow_run.conclusion == 'success' &&
(github.event.workflow_run.event == 'pull_request' ||
github.event.workflow_run.event == 'push')
steps:
- uses: plotly/nitpix@main # TODO: pin to @v1 once released

Check failure on line 41 in .github/workflows/nitpix.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use full commit SHA hash for this dependency.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGqBlkMKz-IngxBU&open=AZ84FGqBlkMKz-IngxBU&pullRequest=3873

Check warning on line 41 in .github/workflows/nitpix.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGqBlkMKz-IngxBV&open=AZ84FGqBlkMKz-IngxBV&pullRequest=3873
with:
baseline-branch: nitpix-baselines
40 changes: 3 additions & 37 deletions .github/workflows/post-test-status.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,43 +65,9 @@ jobs:
}
}

- name: Post Percy status for fork/Dependabot PRs
# Percy needs PERCY_TOKEN to run, which is unavailable to fork PRs (and to
# Dependabot unless added to Dependabot secrets). Without a build, the
# Percy GitHub App never posts the required `percy/dash` status and the PR
# is blocked. Post a success status here so the check resolves — but only
# if Percy hasn't already posted one, so a real Percy result is never
# clobbered (e.g. when Dependabot does have the token).
if: >
github.event.workflow_run.head_repository.full_name != github.repository ||
github.event.workflow_run.actor.login == 'dependabot[bot]'
uses: actions/github-script@v7
with:
script: |
const { owner, repo } = context.repo;
const sha = context.payload.workflow_run.head_sha;
const statusContext = 'percy/dash';

const { data: { statuses } } = await github.rest.repos.getCombinedStatus({
owner,
repo,
ref: sha,
});

if (statuses.some(s => s.context === statusContext)) {
console.log(`'${statusContext}' already posted — leaving it untouched.`);
return;
}

await github.rest.repos.createCommitStatus({
owner,
repo,
sha,
state: 'success',
context: statusContext,
description: 'Skipped — Percy unavailable for fork/Dependabot PRs',
});
console.log(`Posted skipped status for ${statusContext}`);
# NOTE: the "Post Percy status for fork/Dependabot PRs" workaround that
# lived here was removed with the move to nitpix (nitpix.yml), which
# handles fork/Dependabot PRs natively via workflow_run.

test-report:
name: Consolidated Test Report (Fork PR)
Expand Down
128 changes: 42 additions & 86 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@
timeout-minutes: 15
run: |
cd bgtests
pytest --headless --nopercyfinalize --junitxml=test-reports/junit_background.xml tests/background_callback -v -s
pytest --headless --junitxml=test-reports/junit_background.xml tests/background_callback -v -s

- name: Cleanup background processes
if: always()
Expand All @@ -340,7 +340,7 @@
timeout-minutes: 15
run: |
cd bgtests
pytest --headless --nopercyfinalize --junitxml=test-reports/junit_async.xml tests/async_tests -v -s
pytest --headless --junitxml=test-reports/junit_async.xml tests/async_tests -v -s

- name: Upload test results
if: always()
Expand Down Expand Up @@ -422,7 +422,7 @@
cp -r tests bgtests/tests
cd bgtests
touch __init__.py
pytest --headless --nopercyfinalize tests/backend_tests -v -s
pytest --headless tests/backend_tests -v -s

table-unit:
name: Table Unit/Lint Tests (Python ${{ matrix.python-version }})
Expand Down Expand Up @@ -536,7 +536,7 @@
- name: Run Table Server Tests
run: |
cd components/dash-table
pytest --nopercyfinalize --headless --junitxml=test-reports/junit_table.xml --splits 3 --group ${{ matrix.test-group }}
pytest --headless --junitxml=test-reports/junit_table.xml --splits 3 --group ${{ matrix.test-group }}

- name: Upload test results
if: always()
Expand Down Expand Up @@ -605,7 +605,7 @@
cp -r tests wstests/tests
cd wstests
touch __init__.py
pytest --headless --nopercyfinalize tests/websocket -v -s
pytest --headless tests/websocket -v -s

test-main:
name: Main Dash Tests (Python ${{ matrix.python-version }}, Group ${{ matrix.test-group }})
Expand All @@ -619,17 +619,10 @@
test-group: ["1", "2", "3"]

env:
PERCY_TOKEN: ${{ matrix.python-version == '3.12' && secrets.PERCY_TOKEN || '' }}
PERCY_ENABLE: ${{ matrix.python-version == '3.12' && '1' || '0' }}
PERCY_PARALLEL_TOTAL: -1
# Pin the build identity so every shard joins the same parallel build and
# Percy links it to the PR. Auto-detection otherwise uses the ephemeral
# merge SHA (refs/pull/N/merge), so the build never shows up on the PR.
PERCY_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_attempt }}
PERCY_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
PERCY_BRANCH: ${{ github.head_ref || github.ref_name }}
PERCY_PULL_REQUEST: ${{ github.event.pull_request.number }}
PERCY_TARGET_BRANCH: ${{ github.base_ref }}
# Visual snapshots (nitpix) are captured on a single matrix leg so
# parallel legs don't produce duplicate snapshot names. When unset,
# percy_snapshot() is a no-op.
NITPIX_SNAPSHOT_DIR: ${{ matrix.python-version == '3.12' && '/tmp/nitpix-snapshots' || '' }}

steps:
- name: Checkout repository
Expand Down Expand Up @@ -680,16 +673,14 @@
run: npm run setup-tests.py

- name: Run main integration tests
if: matrix.python-version != '3.12'
run: pytest --headless --nopercyfinalize --junitxml=test-reports/junit_intg.xml tests/integration --splits 3 --group ${{ matrix.test-group }}
run: pytest --headless --junitxml=test-reports/junit_intg.xml tests/integration --splits 3 --group ${{ matrix.test-group }}

- name: Run main integration tests with Percy
if: matrix.python-version == '3.12'
uses: ./.github/actions/percy-exec
- name: Upload visual snapshots
if: always() && matrix.python-version == '3.12'
uses: plotly/nitpix/upload@main # TODO: pin to @v1 once released

Check warning on line 680 in .github/workflows/testing.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGrslkMKz-IngxBZ&open=AZ84FGrslkMKz-IngxBZ&pullRequest=3873

Check failure on line 680 in .github/workflows/testing.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use full commit SHA hash for this dependency.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGrrlkMKz-IngxBY&open=AZ84FGrrlkMKz-IngxBY&pullRequest=3873
with:
command: pytest --headless --nopercyfinalize --junitxml=test-reports/junit_intg.xml tests/integration --splits 3 --group ${{ matrix.test-group }}
percy-token: ${{ secrets.PERCY_TOKEN }}
browser-executable: ${{ steps.setup-chrome.outputs.chrome-path }}
name: main-${{ matrix.test-group }}
path: /tmp/nitpix-snapshots

- name: Upload test results
if: always()
Expand Down Expand Up @@ -722,17 +713,9 @@
python-version: ["3.9", "3.12"]

env:
PERCY_TOKEN: ${{ matrix.python-version == '3.12' && secrets.PERCY_TOKEN || '' }}
PERCY_ENABLE: ${{ matrix.python-version == '3.12' && '1' || '0' }}
PERCY_PARALLEL_TOTAL: -1
# Pin the build identity so every shard joins the same parallel build and
# Percy links it to the PR. Auto-detection otherwise uses the ephemeral
# merge SHA (refs/pull/N/merge), so the build never shows up on the PR.
PERCY_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_attempt }}
PERCY_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
PERCY_BRANCH: ${{ github.head_ref || github.ref_name }}
PERCY_PULL_REQUEST: ${{ github.event.pull_request.number }}
PERCY_TARGET_BRANCH: ${{ github.base_ref }}
# Visual snapshots (nitpix) are captured on a single matrix leg so
# parallel legs don't produce duplicate snapshot names.
NITPIX_SNAPSHOT_DIR: ${{ matrix.python-version == '3.12' && '/tmp/nitpix-snapshots' || '' }}

steps:
- name: Checkout repository
Expand Down Expand Up @@ -784,18 +767,15 @@
run: npm ci

- name: Run HTML components tests
if: matrix.python-version != '3.12'
working-directory: components/dash-html-components
run: pytest --headless --nopercyfinalize --junitxml=test-reports/junit_html.xml
run: pytest --headless --junitxml=test-reports/junit_html.xml

- name: Run HTML components tests with Percy
if: matrix.python-version == '3.12'
uses: ./.github/actions/percy-exec
- name: Upload visual snapshots
if: always() && matrix.python-version == '3.12'
uses: plotly/nitpix/upload@main # TODO: pin to @v1 once released

Check failure on line 775 in .github/workflows/testing.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use full commit SHA hash for this dependency.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGrslkMKz-IngxBa&open=AZ84FGrslkMKz-IngxBa&pullRequest=3873

Check warning on line 775 in .github/workflows/testing.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGrslkMKz-IngxBb&open=AZ84FGrslkMKz-IngxBb&pullRequest=3873
with:
command: pytest --headless --nopercyfinalize --junitxml=test-reports/junit_html.xml
percy-token: ${{ secrets.PERCY_TOKEN }}
browser-executable: ${{ steps.setup-chrome.outputs.chrome-path }}
working-directory: components/dash-html-components
name: html
path: /tmp/nitpix-snapshots

- name: Upload test results
if: always()
Expand Down Expand Up @@ -918,17 +898,9 @@
test-group: ["1", "2", "3"]

env:
PERCY_TOKEN: ${{ matrix.python-version == '3.12' && secrets.PERCY_TOKEN || '' }}
PERCY_ENABLE: ${{ matrix.python-version == '3.12' && '1' || '0' }}
PERCY_PARALLEL_TOTAL: -1
# Pin the build identity so every shard joins the same parallel build and
# Percy links it to the PR. Auto-detection otherwise uses the ephemeral
# merge SHA (refs/pull/N/merge), so the build never shows up on the PR.
PERCY_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_attempt }}
PERCY_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
PERCY_BRANCH: ${{ github.head_ref || github.ref_name }}
PERCY_PULL_REQUEST: ${{ github.event.pull_request.number }}
PERCY_TARGET_BRANCH: ${{ github.base_ref }}
# Visual snapshots (nitpix) are captured on a single matrix leg so
# parallel legs don't produce duplicate snapshot names.
NITPIX_SNAPSHOT_DIR: ${{ matrix.python-version == '3.12' && '/tmp/nitpix-snapshots' || '' }}

steps:
- name: Checkout repository
Expand Down Expand Up @@ -980,7 +952,14 @@
cd components/dash-core-components
npm ci
npm run test:jest
pytest --headless --nopercyfinalize --junitxml=test-reports/junit_intg.xml --junitprefix="components.dash-core-components" tests/integration --splits 3 --group ${{ matrix.test-group }}
pytest --headless --junitxml=test-reports/junit_intg.xml --junitprefix="components.dash-core-components" tests/integration --splits 3 --group ${{ matrix.test-group }}

- name: Upload visual snapshots
if: always() && matrix.python-version == '3.12'
uses: plotly/nitpix/upload@main # TODO: pin to @v1 once released

Check failure on line 959 in .github/workflows/testing.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use full commit SHA hash for this dependency.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGrslkMKz-IngxBc&open=AZ84FGrslkMKz-IngxBc&pullRequest=3873

Check warning on line 959 in .github/workflows/testing.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ84FGrslkMKz-IngxBd&open=AZ84FGrslkMKz-IngxBd&pullRequest=3873
with:
name: dcc-${{ matrix.test-group }}
path: /tmp/nitpix-snapshots

- name: Upload test results
if: always()
Expand Down Expand Up @@ -1084,35 +1063,12 @@
retention-days: 7
if-no-files-found: ignore

percy-finalize:
name: Finalize Percy Snapshots
needs: [test-main, dcc-test, html-test]
runs-on: ubuntu-latest
if: always()
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
# Must match the snapshot jobs so finalize targets the same parallel build
# and the result is attached to the PR head commit, not the merge SHA.
PERCY_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_attempt }}
PERCY_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
PERCY_BRANCH: ${{ github.head_ref || github.ref_name }}
PERCY_PULL_REQUEST: ${{ github.event.pull_request.number }}
PERCY_TARGET_BRANCH: ${{ github.base_ref }}
steps:
- name: Finalize Main Percy Build
if: |
env.PERCY_TOKEN != '' && (
needs.test-main.result != 'skipped' ||
needs.dcc-test.result != 'skipped' ||
needs.html-test.result != 'skipped'
)
run: |
npm install -g @percy/cli
npx percy build:finalize

- name: Skip Percy finalize (fork PR)
if: env.PERCY_TOKEN == ''
run: echo "::notice::Skipping Percy finalize (no token available - likely a fork PR)"
# Visual diffing (nitpix) runs in a separate workflow (nitpix.yml) triggered
# by workflow_run: it downloads the nitpix-snapshots-* artifacts uploaded by
# the jobs above, diffs them against the baselines on the nitpix-baselines
# branch, and posts the PR comment + nitpix/visual commit status. Running it
# over there (base-repo context) is what makes it work for fork PRs and
# Dependabot, which get a read-only token in this workflow.

test-report:
name: Consolidated Test Report
Expand Down Expand Up @@ -1181,7 +1137,7 @@

artifacts:
name: Store Build Artifacts
needs: [build, percy-finalize]
needs: [build, test-main]
runs-on: ubuntu-latest
if: |
github.event_name == 'push' &&
Expand Down
Loading
Loading