Skip to content
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
run: uv run python scripts/check_engine_locks.py

- name: Verify release version sources
run: uv run python scripts/release_evidence.py --tag v0.2.0 --check-version-only
run: uv run python scripts/release_evidence.py --tag v0.2.1 --check-version-only

- name: Build Python distributions
run: uv build
Expand Down Expand Up @@ -111,6 +111,9 @@ jobs:
- name: Verify checked catalog artifacts
run: uv run python scripts/check_examples.py --check

- name: Verify public gallery matches reviewed live baselines
run: uv run python scripts/sync_dashboard_samples.py --check

- name: Generate every target variant and verify native expectations
run: uv run python scripts/check_corpus.py

Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ concurrency:
cancel-in-progress: false

jobs:
visual-regression:
name: Release visual regression
uses: ./.github/workflows/visual-regression.yml
with:
suite: full
target: all
update_snapshots: false

official-engine:
name: Release validator ${{ matrix.engine }}
runs-on: ubuntu-latest
Expand Down Expand Up @@ -78,7 +86,7 @@ jobs:

build:
name: Build and attest once
needs: official-engine
needs: [official-engine, visual-regression]
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
Expand Down
239 changes: 239 additions & 0 deletions .github/workflows/visual-regression.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
name: Splunk visual regression

on:
pull_request:
paths:
- ".github/workflows/visual-regression.yml"
- "examples/catalog/**"
- "integration/splunk-visual/**"
- "splunk_dashboard_studio/catalog.py"
- "splunk_dashboard_studio/codec.py"
- "splunk_dashboard_studio/contracts.py"
- "splunk_dashboard_studio/generation.py"
- "splunk_dashboard_studio/models.py"
- "splunk_dashboard_studio/source_templates.py"
- "splunk_dashboard_studio/template_data/**"
- "splunk_dashboard_studio/validation.py"
schedule:
- cron: "23 6 * * *"
workflow_dispatch:
inputs:
suite:
description: Render scope
required: true
default: smoke
type: choice
options: [smoke, full]
target:
description: Full-suite target selection
required: true
default: all
type: choice
options: [all, "9.4.3", "10.0.0", "10.2.0", "10.4.0"]
update_snapshots:
description: Generate candidate baselines for artifact review
required: true
default: false
type: boolean
workflow_call:
inputs:
suite:
required: true
type: string
target:
required: false
default: all
type: string
update_snapshots:
required: false
default: false
type: boolean

permissions:
contents: read

concurrency:
group: visual-${{ github.workflow }}-${{ github.ref }}-${{ inputs.suite || 'scheduled' }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
matrix-config:
name: Resolve target matrix
runs-on: ubuntu-24.04
timeout-minutes: 2
outputs:
matrix: ${{ steps.configuration.outputs.matrix }}
steps:
- name: Resolve target matrix
id: configuration
env:
REQUESTED_TARGET: ${{ inputs.target || 'all' }}
shell: bash
run: |
set -euo pipefail
case "${REQUESTED_TARGET}" in
all|"")
echo 'matrix={"target":["9.4.3","10.0.0","10.2.0","10.4.0"]}' >>"${GITHUB_OUTPUT}"
;;
9.4.3|10.0.0|10.2.0|10.4.0)
echo "matrix={\"target\":[\"${REQUESTED_TARGET}\"]}" >>"${GITHUB_OUTPUT}"
;;
*)
echo "Unsupported target: ${REQUESTED_TARGET}" >&2
exit 2
;;
esac

visual-smoke:
name: Visual smoke (10.4.0)
needs: matrix-config
if: github.event_name == 'pull_request' || inputs.suite == 'smoke'
runs-on: ubuntu-24.04
timeout-minutes: 25
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python 3.12
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: "3.12"

- name: Set up uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
with:
version: "0.11.25"
enable-cache: true
save-cache: false

- name: Set up Node 24 for browser QA only
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "24"
cache: npm
cache-dependency-path: integration/splunk-visual/package-lock.json

- name: Install Python runtime and browser harness
run: |
uv sync --frozen --no-dev
npm ci --prefix integration/splunk-visual --ignore-scripts --no-audit --no-fund
npm exec --prefix integration/splunk-visual -- playwright install --with-deps chromium

- name: Run disposable Splunk render smoke
env:
SPLUNK_PASSWORD: Visual-QA-${{ github.run_id }}-${{ github.run_attempt }}!
SPLUNK_TARGET: "10.4.0"
SPLUNK_UPDATE_SNAPSHOTS: ${{ inputs.update_snapshots && '1' || '0' }}
SPLUNK_VISUAL_ARTIFACTS: ${{ runner.temp }}/splunk-visual-10.4.0
SPLUNK_VISUAL_OUTPUT: ${{ runner.temp }}/splunk-visual-10.4.0
SPLUNK_VISUAL_SUITE: smoke
run: integration/splunk-visual/run.sh

- name: Build QA overview after a partial browser failure
if: failure()
env:
SPLUNK_VISUAL_ARTIFACTS: ${{ runner.temp }}/splunk-visual-10.4.0
SPLUNK_VISUAL_TARGET: "10.4.0"
working-directory: integration/splunk-visual
shell: bash
run: |
if find "${SPLUNK_VISUAL_ARTIFACTS}/screenshots" -name '*.png' -print -quit | grep -q .; then
npm run qa:overview
fi

- name: Upload smoke evidence
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: splunk-visual-smoke-10.4.0
path: ${{ runner.temp }}/splunk-visual-10.4.0
if-no-files-found: error
retention-days: 14

- name: Upload candidate baselines
if: inputs.update_snapshots
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: candidate-baselines-10.4.0
path: integration/splunk-visual/baselines/10.4.0
if-no-files-found: error
retention-days: 14

visual-full:
name: Visual full (${{ matrix.target }})
needs: matrix-config
if: github.event_name == 'schedule' || inputs.suite == 'full'
runs-on: ubuntu-24.04
timeout-minutes: 35
strategy:
fail-fast: false
max-parallel: 2
matrix: ${{ fromJSON(needs.matrix-config.outputs.matrix) }}
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python 3.12
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: "3.12"

- name: Set up uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
with:
version: "0.11.25"
enable-cache: true
save-cache: false

- name: Set up Node 24 for browser QA only
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "24"
cache: npm
cache-dependency-path: integration/splunk-visual/package-lock.json

- name: Install Python runtime and browser harness
run: |
uv sync --frozen --no-dev
npm ci --prefix integration/splunk-visual --ignore-scripts --no-audit --no-fund
npm exec --prefix integration/splunk-visual -- playwright install --with-deps chromium

- name: Run disposable Splunk full render suite
env:
SPLUNK_PASSWORD: Visual-QA-${{ github.run_id }}-${{ strategy.job-index }}!
SPLUNK_TARGET: ${{ matrix.target }}
SPLUNK_UPDATE_SNAPSHOTS: ${{ inputs.update_snapshots && '1' || '0' }}
SPLUNK_VISUAL_ARTIFACTS: ${{ runner.temp }}/splunk-visual-${{ matrix.target }}
SPLUNK_VISUAL_OUTPUT: ${{ runner.temp }}/splunk-visual-${{ matrix.target }}
SPLUNK_VISUAL_SUITE: full
run: integration/splunk-visual/run.sh

- name: Build QA overview after a partial browser failure
if: failure()
env:
SPLUNK_VISUAL_ARTIFACTS: ${{ runner.temp }}/splunk-visual-${{ matrix.target }}
SPLUNK_VISUAL_TARGET: ${{ matrix.target }}
working-directory: integration/splunk-visual
shell: bash
run: |
if find "${SPLUNK_VISUAL_ARTIFACTS}/screenshots" -name '*.png' -print -quit | grep -q .; then
npm run qa:overview
fi

- name: Upload target evidence
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: splunk-visual-full-${{ matrix.target }}
path: ${{ runner.temp }}/splunk-visual-${{ matrix.target }}
if-no-files-found: error
retention-days: 14

- name: Upload candidate baselines
if: inputs.update_snapshots
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: candidate-baselines-${{ matrix.target }}
path: integration/splunk-visual/baselines/${{ matrix.target }}
if-no-files-found: error
retention-days: 14
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ node_modules/
compatibility-report.json
corpus.jsonl
schema.json
/integration/splunk-visual/artifacts/
/integration/splunk-visual/playwright-report/
/integration/splunk-visual/test-results/
/integration/splunk-visual/blob-report/
/integration/splunk-visual/storage-state.json
23 changes: 19 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ candidate” describe repository state and do not claim a GitHub or PyPI release

## Unreleased

### 0.2.0 release candidate
### 0.2.1 release candidate

Added:

Expand All @@ -19,19 +19,34 @@ Added:
diffs.
- Engine-lock consistency, generated-example drift, release-evidence, checksum, artifact
attestation, and PyPI trusted-publishing workflows.
- An auto-accepting, integration-only Splunk Free fixture for original-SPL dispatch, exact synthetic
result math, REST publish/readback, Dashboard Studio browser rendering, and state coverage.
- Locked Playwright screenshot regression, ARIA and trace evidence, QA overview generation, and a
provider-neutral advisory vision report contract.
- Reviewed full-suite render baselines for pinned Splunk Enterprise 9.4.3, 10.0.0, 10.2.0, and
10.4.0 images, with a machine-readable provenance inventory.
- A provenance-locked source-template API and CLI for the Apache-2.0 Splunk Health dashboard from
`rcastley/splunk-custom-visualizations`, including its eight integration-only custom
visualizations and manifest-driven render contracts.
- A distinct app-free Splunk Health compatibility port using built-in visualizations, validated
with live Splunk Enterprise 9.4.3 and 10.0.0 render baselines.
- A five-image public gallery synchronized byte-for-byte from reviewed live Splunk baselines.
- Operational security, skills, architecture, compatibility, and catalog documentation.

Changed:

- Package and runtime version to `0.2.0`.
- Package and runtime version to `0.2.1`.
- Minimum Python version from 3.14 to 3.12.
- The 10.4 network graph type to the official `splunk.networkGraph` spelling.
- Native custom-visualization detection to recognize app-qualified visualization types and enforce
the Splunk Enterprise 10.2 feature boundary.
- Compatibility corpus from eight generic cases per target to include every eligible catalog
definition.
definition and source template; app-free source ports run through official NPM validators while
app-qualified custom definitions remain live-fixture-only.

Deferred:

- Live Splunk publish/readback fixture and HTTP adapter.
- An unattended vision provider or external screenshot-upload credential.
- Machine-enforced ACL, sensitive-index, or publication policy.
- Splunk Cloud, 9.2.x, and 9.3.x support.

Expand Down
Loading
Loading