Skip to content

fix!: security updates and drop Python 3.10 on stable/27.1 - #645

Merged
viseshrp merged 48 commits into
stable/27.1from
codex/fix-certifi-stable-27.1
Nov 2, 2026
Merged

viseshrp merged 48 commits into
stable/27.1from
codex/fix-certifi-stable-27.1

Conversation

@viseshrp

@viseshrp viseshrp commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Addresses https://ado.internal.synopsys.com/tfs/ANSYS_development/Portfolio/_workitems/edit/1534172
Also https://ado.internal.synopsys.com/tfs/ANSYS_Development/Portfolio/_workitems/edit/1536094, https://ado.internal.synopsys.com/tfs/ANSYS_Development/Portfolio/_workitems/edit/1536102 and https://ado.internal.synopsys.com/tfs/ANSYS_Development/Portfolio/_workitems/edit/1536105

Security updates for stable/27.1 ahead of 1.0.0rc4, and drops Python 3.10.

Security

  • djangorestframework 3.18.3 (cap <3.19.0): CVE-2026-114136, CVE-2026-114137.
  • Django 5.2.18 and Pillow 13.0.0. Pillow 13 can't save I-mode images as PNG, so report_utils.png_compatible_image converts them to I;16 first (same output as Pillow 12).
  • Playwright 1.64.1: bundled Node.js 24.22.1 distrusts the eMudhra intermediates; uses Chromium build 1248.
  • CI: ansys/actions v11.1.3, pypa/gh-action-pypi-publish v1.14.3; Security Scan runs on stable/**.

certifi is not pinned here. ADR guarantees certifi ≥ 2026.10.19 in its own Python environment; SECURITY.md tells users who manage their own environment to update it.

Browser PDF build fallback

If ADR ships a different browser build than Playwright expects, or the expected build can't be determined, the renderer launches the browser from the ADR installation and logs a warning. If that browser is missing, it raises ADRException. It never uses another browser. So this release works with ADR 27.1 images that still ship build 1223.

Breaking: Python 3.10 dropped

requires-python is now >=3.11, <3.15. 3.10 is end-of-life, has no eMudhra fix, and current Pillow/Django don't support it.

Minimum versions

Runtime floors now match ADR 26.1's bundled versions (requests 2.32.4, Pillow 11.1.0, python-dateutil 2.9.0.post0, pytz 2024.2, psutil 7.2.1, psycopg 3.2.12, bleach 6.3.0). statsmodels needs 0.14.5+, because 0.14.2–0.14.4 can't import with SciPy 1.16+.

constraints/v261.txt is unchanged, so 26.1-profile installs keep Django 4.2 and DRF 3.15.

Validation

  • Pre-commit, lock consistency, smoke imports and wheel build pass locally; full ADR tests run in CI.
  • Serverless and service-mode workflows tested manually against ADR 26.1, with and without the profile and at the new floors: same results as stable/27.1.
  • Browser PDF tested with Chromium builds 1248 and 1223 under Playwright 1.64.1.

Please squash-merge.

Work item: addresses https://ado.internal.synopsys.com/tfs/ANSYS_development/Portfolio/_workitems/edit/1534172

🤖 Generated with Claude Code

Require certifi>=2026.10.19 for runtime installations and update the stable
lock to certifi 2026.10.23. This removes trust in the affected emSign root
used by the compromised eMudhra intermediates (GHSA-6q48-6c7w-9gw2).
Keep every other locked package version and record unchanged, apart from
the project's new direct dependency metadata.

Validated the frozen environment and built wheel metadata on Windows with
Python 3.14.7. The library's Requests session rejected all 14 compromised
certificate chains and accepted the valid control. Twelve focused
browser-PDF/cookie tests and make smoketest passed; uv lock --locked passed.

Canonical pre-commit and make check hit the host's existing WinError 1314
license-template symlink limitation. All hooks passed with a byte-identical
temporary custom template and temporary configuration; tracked hook
configuration was unchanged.
@codecov-commenter

codecov-commenter commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.06%. Comparing base (6b07074) to head (6302be6).

Additional details and impacted files
@@               Coverage Diff               @@
##           stable/27.1     #645      +/-   ##
===============================================
+ Coverage        82.00%   82.06%   +0.05%     
===============================================
  Files               32       32              
  Lines             9399     9422      +23     
  Branches          1691     1693       +2     
===============================================
+ Hits              7708     7732      +24     
  Misses            1194     1194              
+ Partials           497      496       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Require uv 0.13.5 or newer, lock that version, and use it as the shared
CI bootstrap default. This adds compromised eMudhra intermediate-key
rejection to uv's independent TLS certificate store.

Regenerate lock metadata with uv 0.13.5 while preserving certifi and
all other package records. Python and ADR dependencies stay unchanged.

Validation: official bootstrap SHA-256 verified; bootstrap and project
executables reject all 14 compromised chains and reach HTTP on the valid
control. Old uv is blocked; frozen sync, lock consistency, smoke tests,
and wheel build pass. All pre-commit hooks pass with an identical
temporary license template; the canonical Windows hook encounters
WinError 1314.
@viseshrp viseshrp changed the title fix: require corrected certifi CA bundle fix: correct certifi and uv certificate trust Oct 26, 2026
Require pip >=26.2.2 in the development extra and lock 26.2.2, including
its published artifact hashes. This updates pip's independent vendored
certifi bundle to 2026.10.19 while preserving standalone certifi 2026.10.23,
uv 0.13.5, and all other locked package records.

The official pip wheel matches the SHA-256 published by the Python
security team; all 452 installed pip files match that wheel. Both the
installed CA bundle and actual pip CLI reject all 14 compromised chains
and reach HTTP on the valid control using anonymous metadata-only probes.

Lock consistency, frozen installation, smoke tests, and wheel metadata
checks pass. All pre-commit hooks pass with a byte-identical temporary
license template; the canonical Windows hook encounters WinError 1314.
Python, virtualenv, CI configuration, and ADR components are unchanged.
@viseshrp viseshrp changed the title fix: correct certifi and uv certificate trust fix: correct certifi, uv, and pip certificate trust Oct 26, 2026
viseshrp and others added 3 commits October 26, 2026 16:51
Security Scan also ran on v1.1.0.dev0. The wheelhouse action rejected
that marker because its tag version differs from the timestamped
package metadata. Apply the development-tag exclusion already used
by CI-CD and draft releases.

Keep main pushes, PRs, and final/RC tag scans enabled.
Verified tag-filter cases, workflow schema hooks, and smoke imports.
All hooks passed with the supported Windows license-template option;
the default hook is blocked by Windows symlink privileges.

(cherry picked from commit 01ee972)
Update virtualenv and its hook environment seeds, Playwright's embedded Node,
the PyPI publisher action, and the Python security baseline used by CI. Pin
official Python build hashes so patched Windows and Linux interpreters are
available for each maintained minor. Extend security scans to stable branches.

Retain Python 3.10 package compatibility and document its upstream security
limitation and deployment-owned trust stores. Preserve the existing certifi,
pip, and uv fixes, all other locked versions, and the excluded gRPC record.

Verified official artifacts, fresh virtualenv and six hook environments, 38
focused tests, lock consistency, frozen installation, smoke tests, and wheel
metadata. Python, Requests, pip, uv, and embedded Node reject all 14 compromised
chains and accept the valid control. Windows hooks pass with a byte-identical
temporary license template; the canonical hook needs symlink privileges.
@viseshrp viseshrp changed the title fix: correct certifi, uv, and pip certificate trust fix: harden certificate trust on stable/27.1 Oct 26, 2026
viseshrp and others added 12 commits October 26, 2026 17:15
Stop exporting UV_PYTHON as the managed base interpreter. That override takes
precedence over the separate virtualenvs created by Ansys code-style and
vulnerability actions, causing their uv pip commands to fail against an
externally managed interpreter. Keep the patched interpreter on PATH and check
the interpreter actually selected by subsequent CI steps.

Verified the Windows bootstrap, active virtualenv selection with an offline
installer dry run, lock consistency, frozen installation, smoke tests, and all
hooks with the documented temporary Windows license-template workaround.
Playwright 1.64.1 looks for browser revision 1248, which ADR 27.1 does not
package. Resolve and validate the executable inside the revision named by
ADR's existing metadata, then pass it through Playwright's executable_path API.
Keep the product browser and metadata format unchanged while updating the
driver's independent Node certificate store.

Update real-browser tests to launch that same product executable. Cover Windows
and Linux paths, missing or non-file executables, and renderer selection despite
an unrelated browser-cache override. Document that the Node fix does not update
the vendor browser's own trust store.

Validation: 41 focused tests, Python 3.10 grammar, lock consistency, frozen
installation, smoke tests, wheel build, and all hooks with the documented
Windows license-template workaround. Both verified Windows and Linux Node
binaries reject all 14 compromised chains and accept the valid control.
The normal ADR integration matrix will validate protocol/PDF compatibility.
The vulnerability check reports SFTY-20260824-88474 with Django 5.2.17
from main's lockfile. Update only Django to the 5.2.18 security patch.
All other locked package entries and direct dependency constraints remain
unchanged, keeping the 27R2 preparation free of the broad dependency refresh.

Validation: 40 compatibility tests and smoke imports passed. All pre-commit
hooks passed with the supported license-template copy on Windows. Compared
the lockfile package records with main to verify Django is the only change.

(cherry picked from commit fa22d62)
Require grpcio 1.85.0 in the test extra and update only its lock record.
This replaces the default CA store used by the existing DPF test dependency.
Keep DPF 0.16.1, its server, and every other locked package unchanged.
Document the separate handling required for explicit gRPC CA overrides.

Validation: 93 focused tests, frozen installation, lock consistency, smoke
imports, and the wheel build passed. All 14 compromised chain variants are
rejected by native gRPC on loopback, with a valid local RPC control. The
installed bundle also rejects all 14 public test chains and accepts the
valid HTTPS control using unpatched Python 3.10. All locked gRPC artifacts
match official PyPI hashes. Pre-commit passed with the identical upstream
license template copied locally to avoid Windows symlink privilege limits.
Document the runner's independent Node runtime and OS trust store. Current
CI logs report runner 2.338.0; its upstream build bundles Node 24.21.0.
Runner 2.338.2 bundles patched Node 24.22.1. Explain the required runner
update or verified backport and link GitHub's hosted-image rollout issue.

Selecting a patched Node on PATH does not update the JavaScript Actions
runtime. Passing dependency checks alone cannot establish that the
host-managed bootstrap path is fixed.

Validation: checked the official runner sources and release, ran lock
consistency, frozen installation, smoke imports, and pre-commit. Local
license validation uses the identical template copy required on Windows.
Refresh ca-certificates in the shared Linux CI setup before installing
project tools. Rebuild the standard CA bundle and require the fixed
20260816ubuntu0.<Ubuntu release>.1 package baseline from USN-8944-1.
Keep separately installed enterprise CAs and all Python lock records.

Validate the exact shared setup commands in Ubuntu 24.04 containers.
Native OpenSSL rejects all 14 compromised chains and reaches HTTP 200 on
the valid control. A second pass preserves an added private control CA
and repeats all TLS probes successfully. Pre-commit, lock consistency,
frozen installation, and smoke imports pass; Windows license checking
uses the identical upstream template copy for the symlink limitation.

The initial checkout and JavaScript Actions runtime remain managed by
the runner platform. Document that separate update requirement.
Restore playwright==1.60.0 and the browser-PDF renderer and tests from
stable/27.1. The 1.64.1 bump only updated the driver's embedded Node
runtime, which this library never uses for TLS: offline exports load
file:// URLs with external requests blocked, and live report URLs go
through Chromium's own network stack. The bump also required launching
an older ADR-packaged browser through hard-coded executable paths.

uv lock changes only the Playwright record and its specifier.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove the custom python-build-standalone installer, its checked-in
download metadata, the CI interpreter guard script, and that script's
tests. Restore actions/setup-python with minor-version matrices, which
resolve the newest patch release and keep Python 3.10 covered, matching
the package's requires-python range.

Drop the Ubuntu ca-certificates refresh from the shared setup action.
It added an apt-get network step to every Linux job, including release
jobs, while GitHub rolls the fix into its hosted images.

Restore the CI uv default to latest; tool.uv.required-version already
enforces the patched uv floor.

Keep the ansys/actions v11.1.3 and pypi-publish v1.14.3 updates, and
the Security Scan triggers for stable/** branches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The per-hook pip>=26.2.2 entries only forced hook environments to be
rebuilt. The upgraded pip is fetched by each environment's existing pip,
and virtualenv>=21.14.13 in the dev extra already seeds the patched pip
into new hook environments.

Keep the certifi floor on the two hooks whose environments install
their own certifi copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reduce the SECURITY.md section to what package users need: the certifi
floor, the patched CPython releases, the Python 3.10 caveat, and the
separate installer, gRPC, OS, and product trust stores. Remove notes
about CI internals and the reverted Playwright change. The section
heading is unchanged, so the README link still resolves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Raise the djangorestframework cap to <3.19.0 and lock 3.18.3, which
fixes CVE-2026-114136 and CVE-2026-114137. Lock Pillow 13.0.0 for
Python 3.11+; Pillow 13 drops Python 3.10, so 3.10 keeps 12.3.0.

Django stays on 5.2.18, the newest 5.2 LTS patch. Django 6 requires
Python 3.12+ and is out of scope for this stable branch.

Only these package records change in uv.lock. Verified lock
consistency, frozen sync, smoke imports, pre-commit hooks, and the
browser-path tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Require Python 3.11 through 3.14 for 1.0.0rc4. Python 3.10 is
end-of-life, has no upstream fix for the eMudhra certificate incident,
and current Pillow and Django releases no longer support it. ADR ships
Python 3.13+, so product-embedded runtimes are unaffected.

- pyproject.toml: requires-python >=3.11, drop the 3.10 classifier,
  ruff target py311.
- CI: remove 3.10 from the smoke and test matrices.
- uv.lock: remove the 3.10-only package forks (contourpy, docutils,
  exceptiongroup, ipython, matplotlib, pillow, scipy, sphinx). No
  package is upgraded.
- README, getting-started docs, SECURITY.md, AGENTS.md: update the
  supported range and drop the 3.10 caveat.
- CHANGELOG: add an Unreleased section for the Python floor and the
  certifi and djangorestframework security updates.

Verified lock consistency, frozen sync, smoke imports, pre-commit
hooks, browser-path tests, and a wheel build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@viseshrp viseshrp changed the title fix: harden certificate trust on stable/27.1 fix!: security updates and drop Python 3.10 on stable/27.1 Oct 27, 2026
viseshrp and others added 7 commits October 27, 2026 15:46
List the Pillow, Django, dev-tool, and grpcio updates in the Unreleased
Security section. Restore the getting-started page's original line
endings so the diff shows only the supported-Python change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pillow 13 refuses to write I mode images as PNG; Pillow 12 clipped
them to 16 bits on save. Add report_utils.png_compatible_image, which
converts I images to I;16 first, and use it in the service-mode
PIL_image_to_data path and the serverless Image item. The output
matches Pillow 12 byte-for-value (checked against Pillow 12.3.0).

Add tests for the conversion, the pass-through for other modes, and a
32-bit TIFF round trip through PIL_image_to_data; the round-trip test
fails without the fix.

Also correct the changelog: Django 5.2 still supports Python 3.10,
only Pillow 13 and Django 6 do not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Split the Pillow/Django and development-tool notes into separate
bullets so the lines match the file's wrapping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base the Python 3.10 removal on Pillow 13 rather than Django 6, which this
branch does not adopt, and say that Pillow 13.0.0 and Django 5.2.18 are
locked versions rather than new requirements: the pyproject floors are
unchanged.

Verified with pre-commit on CHANGELOG.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The v261 profile pinned Django, django-guardian, DRF and NumPy to the
stack bundled with ADR 26.1 but left Pillow open, so 26.1-profile installs
pulled the newest Pillow (13.0.0). Cap it at >=11.1.0,<12.0.0 to match the
Pillow 11.1.0 that ADR 26.1 bundles while still taking 11.x fixes.

Document in the changelog and the serverless caveats that the 26.1 profile
keeps the 26.1 stack and does not include the Django, DRF or Pillow
security updates; ADR 27.1 is the path for those.

Verified against a local ADR 26.1 install on its bundled Python 3.12.11
with the updated profile (Django 4.2.30, DRF 3.15.2, Pillow 11.3.0): the
serverless suite gives the same results on this branch and on stable/27.1,
and the serverless and service-mode smoke checks pass. No new
compatibility shims are needed. Also ran uv lock --locked, pre-commit
and the smoketest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove the floors this branch added on pip, uv, virtualenv, and grpcio,
the uv required-version, and the certifi additional_dependencies on the
check-github-workflows and add-license-headers pre-commit hooks. These
are unpinned development and test tools that resolve to their latest
releases on their own, so the floors were temporary patches for fixes
the tools ship upstream. pyproject.toml and .pre-commit-config.yaml now
match stable/27.1 for these entries.

The lock keeps the same package versions; only the requires-dist
metadata changed. SECURITY.md and CHANGELOG.md no longer list the
installer and gRPC updates, since users of the library do not get those
tools through it.

Verified with uv lock --locked, pre-commit (all hooks pass except
add-license-headers, which cannot create symlinks on this Windows host
and runs in CI), and tests/smoketest.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the Pillow>=11.1.0,<12.0.0 line added to constraints/v261.txt in
c18bcf8. A different Pillow on the client does not clash with ADR 26.1:

- Service mode: the server runs on its own bundled Python and Pillow
  11.1.0, and the client only sends it image bytes.
- Serverless mode: the 26.1 product code that runs in the client venv
  only calls Pillow from the web upload views (data/views.py upload_file
  and handle_enhanced, data/utils.py convert_image), which serverless
  does not use. It only uses Image.open, Image.size and Image.save, which
  the Pillow 12.0.0 and 13.0.0 release notes do not change.
  pydynamicreporting's own image code already handles the Pillow 13 PNG
  change through png_compatible_image.

Manual testing against an ADR 26.1 install with Pillow 13.0.0 gave the
same results as Pillow 11.3.0 in every serverless and service flow. The
profile stays optional, and serverless/_compat.py remains the safety net
for users who skip it.

The CHANGELOG and caveats.rst now only say that the 26.1 profile keeps
Django 4.2 and djangorestframework 3.15 without their security updates.

Verified with uv lock --locked, pre-commit (all hooks pass except
add-license-headers, which cannot create symlinks on this Windows host
and runs in CI), and tests/smoketest.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
viseshrp and others added 7 commits October 30, 2026 13:08
Users run browser PDF through the browser that ships with ADR and never
need to know about Playwright or PLAYWRIGHT_BROWSERS_PATH. Reword the
service-mode and serverless browser-PDF guides in user terms: no separate
browser install is needed, run one export at a time per Python process,
and a different browser build in the ADR installation still works with a
logged warning. Reword the CHANGELOG entry, the mismatch warning, the
launch log line, and the incomplete-build error the same way.

Verified with the launch-option unit tests (10 passed), pre-commit (all
hooks pass except add-license-headers, which cannot create symlinks on
this Windows host and runs in CI), and tests/smoketest.py. No user doc
under doc/source mentions Playwright any more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The eMudhra fix only has to be guaranteed in the Python environment that
ships with ADR, and ADR pins certifi 2026.10.19 or later there itself.
PyDynamicReporting does not import certifi directly, so stop requiring it
as a direct dependency. requests still pulls certifi in, and new installs
get the latest release. SECURITY.md now tells users who manage their own
environment to update certifi, instead of saying this package requires it.

Relocked with the project's uv 0.13.5: only the certifi entries change.
Verified with uv lock --locked, pre-commit (all hooks pass except
add-license-headers, which cannot create symlinks on this Windows host and
runs in CI), and tests/smoketest.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The expected browser build is read from the chromium-<build> directory in
Playwright's executable path. If a later Playwright drops that directory
name, the build can't be read. The normal launch then only finds a browser
if ADR's folder happens to hold the exact build Playwright wants, and never
falls back to any other browser.

Treat that case like a build mismatch: launch the headless shell named in
ADR's browser metadata and log a warning. If that executable is missing,
raise ADRException saying the expected build is unknown and the ADR
browser build is incomplete. The matching-build case is unchanged.

Tests: replaced the old unknown-build test with one for the ADR-browser
launch and warning, and one for the missing-executable error. Not run
locally: the serverless test setup needs Docker, which isn't running on
this host. Pre-commit (all hooks pass except add-license-headers, which
cannot create symlinks on this Windows host and runs in CI) and
tests/smoketest.py pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since a8f79c9, an unknown expected build launches the ADR browser
executable directly and raises when that file is missing. The mocked
renderer tests used a Mock for chromium.executable_path, which has no
chromium-<build> folder, and a fake product folder named
"packaged-browser-dir" with no executable. So 27 tests in
test_pdf_renderer.py hit the new "cannot determine which browser build"
error in CI on every Python version.

Name the fake product build chromium_headless_shell-1248 and give the
mocked Playwright a matching chromium-1248 executable_path, so these tests
take the normal launch path again. The fallback render test now expects
build 1249 to keep exercising the mismatch launch.

Not run locally: this module's autouse fixture needs an ADR install or
Docker, neither available on this host. pre-commit passes except
add-license-headers, which cannot create symlinks here and runs in CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This reverts commit 8c91dec. The existing renderer tests describe the
expected behavior, so the code is fixed instead of the tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
a8f79c9 made an unknown expected build always require the ADR headless
shell, raising when the file was missing. That broke 27 existing renderer
tests in CI, which expect a normal launch when Playwright's path carries
no build number and the product folder has no packaged executable.

Now an unknown build launches the ADR headless shell only when that file
exists, with a warning; otherwise it keeps the normal Playwright lookup, as
before a8f79c9. That lookup still only searches the ADR folder. Matching
and mismatching builds are unchanged.

My own unknown-build test now expects the normal launch when the shell is
missing. Existing tests are untouched.

Verified: pre-commit (all hooks pass except add-license-headers, which
cannot create symlinks on this Windows host and runs in CI),
tests/smoketest.py, and a direct run of the launch-option function for
match, mismatch with and without the shell, and unknown with and without
the shell. The test module itself needs ADR via Docker, which isn't
available here, so CI runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the expected browser build can't be determined and the ADR headless
shell isn't at its known path, the renderer keeps the default lookup in
the ADR folder. If that launch fails, the user only sees the generic
"Browser PDF rendering failed." error, which existing tests require. Log a
warning before the launch that names the missing location, so the reason
is in the log.

My own unknown-build test now checks that warning. No existing test checks
renderer warnings, so the mocked renderer tests that take this path are
unaffected.

Verified with pre-commit (all hooks pass except add-license-headers, which
cannot create symlinks on this Windows host and runs in CI),
tests/smoketest.py, and a direct run of the launch-option function. The
test module needs ADR via Docker, so CI runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
margalva
margalva previously approved these changes Oct 30, 2026
phchen95
phchen95 previously approved these changes Oct 30, 2026
The ADR Docker image moved from ghcr.io/ansys-internal/adr_dev to
ghcr.io/snps-ansys-internal/adr_dev:latest. CI's pull of the old image is
refused ("denied"), so every Testing job stops before running tests.

Point the CI pull script, the default DOCKER_REPO_URL and
DOCKER_DEV_REPO_URL constants (which the tests and the Service default
use), and the two compatibility tests at the new image. The CHANGELOG
notes the new default.

Verified with pre-commit (all hooks pass except add-license-headers, which
cannot create symlinks on this Windows host and runs in CI) and the two
updated tests in tests/test_compatibility.py. Pulling the new image is
verified by CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@viseshrp
viseshrp dismissed stale reviews from phchen95 and margalva via b2cbbe2 November 2, 2026 17:01
viseshrp and others added 8 commits November 2, 2026 12:30
The ADR Docker image moved to ghcr.io/snps-ansys-internal, which belongs
to the EMU enterprise. This repository's GITHUB_TOKEN cannot read packages
there, so the pull fails with "manifest unknown".

Log in to ghcr.io with the new ADR_GHCR_USERNAME and ADR_GHCR_TOKEN
repository secrets (an EMU account token with read:packages) instead.
tests.yml is a reusable workflow, so it declares both secrets and its
callers, ci_cd.yml and nightly.yml, pass them in.

Dependabot and fork PRs don't receive repository secrets, so their Testing
jobs can't pull the image.

Verified with pre-commit, including the GitHub workflow validator (all
hooks pass except add-license-headers, which cannot create symlinks on this
Windows host and runs in CI). The pull itself is verified by CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the build comparison, which parsed Playwright's executable path
with a regex, with a fallback that sits on top of the original behavior:

- Launch through Playwright's normal lookup in the ADR browser folder, as
  before. When that works, nothing changes.
- Only if that launch fails with a Playwright error, launch the packaged
  headless shell by path and log a warning.
- A launch timeout is not retried, and a missing packaged executable
  re-raises the original error, so the user still gets the same
  "Browser PDF rendering failed." error as before.

This removes _playwright_expected_headless_shell_dir,
_product_browser_launch_options, the specific "incomplete" error and the
unknown-build handling. The new _launch_product_browser is used by
render_pdf and by the real-browser test helper. The pyproject.toml comment
points at the new function.

Tests: replaced this PR's build-comparison tests with tests for the normal
launch, the fallback on Windows and Linux layouts, a missing packaged
executable, a timeout that is not retried, and render_pdf passing the
packaged executable after a failed launch.

Verified with pre-commit (all hooks pass except add-license-headers, which
cannot create symlinks on this Windows host and runs in CI),
tests/smoketest.py, and a direct run of _launch_product_browser for all
four cases. The test module needs ADR via Docker, so CI runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a temporary, non-blocking diagnostic before the existing ADR image pull.
Compare Docker's saved credentials with the workflow inputs without exposing
values, report the PAT owner and scopes, and check package metadata and Docker
manifest authorization from the hosted runner. Preserve the original pull and
its failure status so the diagnostic does not hide the problem.

Validated with focused pre-commit hooks, Bash syntax and workflow-input checks,
and the existing PyDynamicReporting import smoke test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The runner verified that Docker stored the intended EMU credentials and the
PAT has read:packages. GitHub's package API explicitly rejected the runner
with HTTP 403 because its source IP is outside the organization's IP allow
list; the identical local request succeeds with HTTP 200.

Remove the temporary checks now that the cause is established. Preserve the
existing authentication and pull behavior pending an approved runner or
approved static egress range. No credentials were printed or persisted by
the diagnostic.

Validated with focused workflow pre-commit hooks and the existing import
smoke test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The ADR Docker image location only matters to this repository's CI, not
to users, so it doesn't belong in the CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the normal browser launch fails and the packaged headless shell is
missing from the ADR installation, log a warning naming the build folder
that was checked before re-raising the original error. The user-facing
error stays "Browser PDF rendering failed.", as the existing launch
failure test requires, but the log now says why the fallback couldn't
help.

The missing-shell test now checks the warning and the folder it names.

Verified with pre-commit (all hooks pass except add-license-headers, which
cannot create symlinks on this Windows host and runs in CI),
tests/smoketest.py, and a direct run of _launch_product_browser for the
normal launch, fallback, missing executable and timeout cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the normal browser launch fails and the packaged headless shell is
missing, raise "Browser PDF rendering failed: the browser build <build>
in the Ansys installation is incomplete." instead of the generic error,
with the original launch error as the cause. This replaces the log-only
warning from 0de78ad.

The message names only the build folder, not its full path, because the
path contains playwright-browsers and user-facing errors must not mention
Playwright.

test_playwright_pdf_launch_failure_raises_clean_error_without_leaking_playwright
now expects this message; its cause and no-Playwright checks are
unchanged. The missing-shell unit test now expects the ADRException.

Verified with pre-commit (all hooks pass except add-license-headers, which
cannot create symlinks on this Windows host and runs in CI),
tests/smoketest.py, and a direct run of _launch_product_browser: the
updated test's regex matches, the message doesn't mention Playwright, and
the fallback and timeout cases are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The snps-ansys-internal EMU org has an IP allow list that blocks
GitHub-hosted runners, so CI could not pull the ADR image from there even
with a valid EMU token. The image is now copied to ghcr.io/ansys/adr_dev.

Point the CI pull script, DOCKER_REPO_URL, DOCKER_DEV_REPO_URL and the two
compatibility tests at ghcr.io/ansys/adr_dev:latest, and log in with the
repository's GITHUB_TOKEN again. This reverts the ADR_GHCR_USERNAME and
ADR_GHCR_TOKEN secrets in tests.yml, ci_cd.yml and nightly.yml.

Verified with pre-commit, including the GitHub workflow validator (all
hooks pass except add-license-headers, which cannot create symlinks on this
Windows host and runs in CI), and the two updated tests in
tests/test_compatibility.py. The pull itself is verified by CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@viseshrp
viseshrp merged commit 8ff182f into stable/27.1 Nov 2, 2026
50 of 58 checks passed
@viseshrp
viseshrp deleted the codex/fix-certifi-stable-27.1 branch November 2, 2026 22:32
viseshrp added a commit that referenced this pull request Nov 2, 2026
Addresses
https://ado.internal.synopsys.com/tfs/ANSYS_development/Portfolio/_workitems/edit/1534172

## Summary

- Prepare the `stable/27.1` branch for the 1.0.0rc4 release: rename the
Unreleased changelog section to `1.0.0rc4` and set its date to
2026-11-02.
- Reword the browser fallback entry to describe what the code does: when
the normal browser launch fails, PyDynamicReporting retries once with
the browser executable packaged in the ADR installation and logs a
warning. It names the incomplete browser build when that executable is
missing.

## Notes

- Changelog only: no code, dependency, or lock-file changes.
- The release date must equal the day `scripts/tag_release.sh` runs
(`scripts/check_changelog_date.py`). If tagging slips past 2026-11-02, a
date-only PR is needed, as for rc3.

## Verification

- `scripts/check_changelog_date.py 1.0.0rc4`, the check `tag_release.sh`
runs.
- `pre-commit run --files CHANGELOG.md`; every applicable hook passed.
- The fallback entry was checked against local browser-PDF runs on
Windows with a pre-release ADR 27.1 build: a 1223-only package uses the
fallback (Chromium 148) and a 1248-only package uses the normal launch
(Chromium 156). The Linux fallback was not run.
- The post-commit `uv lock --upgrade` refresh from `AGENTS.md` was
intentionally skipped so the locked dependencies stay as released in
#645.
viseshrp added a commit that referenced this pull request Nov 3, 2026
The built-in GITHUB_TOKEN can no longer pull ghcr.io/ansys-internal/adr_dev, so the Testing jobs fail at 'Pull Docker container' with 'denied' before any test runs. Use ghcr.io/ansys/adr_dev:latest instead, exactly as #645 did on stable/27.1.

The image is set in three places that must agree: scripts/pull_adr_image.sh (what CI pulls), DOCKER_REPO_URL and DOCKER_DEV_REPO_URL in constants.py (the default image Docker mode runs, so the pulled image is the one the tests start), and the docker_image labels in tests/test_compatibility.py. The deliberately non-existent image in tests/test_service.py is unchanged.

Verified with uv run pytest tests/test_compatibility.py (37 passed), tests/smoketest.py, pre-commit and uv lock --locked. The pull itself can only be confirmed in CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
viseshrp added a commit that referenced this pull request Nov 5, 2026
Ports #645 (merged into `stable/27.1`) to `main`.

Addresses
https://ado.internal.synopsys.com/tfs/ANSYS_development/Portfolio/_workitems/edit/1534172
Also
https://ado.internal.synopsys.com/tfs/ANSYS_Development/Portfolio/_workitems/edit/1536094,
https://ado.internal.synopsys.com/tfs/ANSYS_Development/Portfolio/_workitems/edit/1536102
and
https://ado.internal.synopsys.com/tfs/ANSYS_Development/Portfolio/_workitems/edit/1536105

## Changes

- **Breaking:** drop Python 3.10. `requires-python` is now `>=3.11,
<3.15`. 3.10 is end-of-life, has no eMudhra fix, and current
Pillow/Django don't support it.
- **Security:**
- djangorestframework 3.18 (cap `<3.19.0`): CVE-2026-114136,
CVE-2026-114137.
- Playwright 1.64.1: its bundled Node.js distrusts the eMudhra
intermediates.
- Pillow 13.0.0 (lockfile). Pillow 13 can't save `I`-mode images as PNG,
so `png_compatible_image` converts them to `I;16` first (same output as
before).
- CI: `pypa/gh-action-pypi-publish` v1.14.3; Security Scan runs on
`stable/**`.
- certifi is not pinned. ADR guarantees certifi ≥ 2026.10.19 in its own
environment; `SECURITY.md` tells users who manage their own environment
to update it.
- **Browser PDF:** if the ADR installation ships a different browser
build than Playwright expects, launch the installation's browser by path
and log a warning. This compares build names; no launch has to fail
first, and a launch failure is never retried or interpreted. A build
without its executable raises `ADRException` before any launch. It never
uses another browser.
- **Browser PDF, extra builds:** the export uses the build named in the
installation's browser metadata and ignores other builds in the folder
(for example after copying a newer ADR package over an older one), with
a warning. The metadata entry must be a plain folder name.
- **Docker image:** the default image moves from
`ghcr.io/ansys-internal/adr_dev` to `ghcr.io/ansys/adr_dev:latest`
(`constants.py`, `scripts/pull_adr_image.sh`,
`tests/test_compatibility.py`), because the built-in token can no longer
pull from `ansys-internal`. This changes the default image for
Docker-mode users.
- **Minimum versions:** runtime floors match ADR 26.1's bundled
versions. statsmodels needs 0.14.5+. `constraints/v261.txt` is
unchanged, so 26.1-profile installs keep Django 4.2 and DRF 3.15.

## Differences from #645

- The browser-PDF logic has moved on from #645 (build-name comparison
instead of retrying a failed launch; metadata-named build).
- The README link to the TLS guidance points at `main` instead of
`stable/27.1`.
- `uv.lock` is regenerated on `main` and refreshed with `uv lock
--upgrade`, so it no longer matches `stable/27.1` exactly. Notably
`python-dateutil` is locked at 4.0.0.
- Django 5.2.18 and `ansys/actions` v11.1.3 are already on `main`.

## Validation

`uv lock --locked`, pre-commit, smoke test and wheel build pass. The
browser-PDF renderer and browser-binary tests pass (169) against a local
ADR 27.1 install. Full ADR/Docker tests run in CI. The manual ADR 26.1
workflow runs were not repeated for this port.

Browser PDF was also checked end to end against a local ADR 27.2
install, which ships Chromium 1223 while this release expects 1248: the
`local_tests` browser-PDF scripts produced 8 correct PDFs (serverless
and service mode, portrait and landscape, rendered by Chromium 148), and
real-browser launch checks covered a leftover 1248 folder next to 1223,
a missing executable (no launch, no leaked temp folders) and a
non-browser executable. The PDFs were produced on `b3cc226bc` and the
launch checks on `c51cc809c`; later commits do not change the path an
older installation takes.

## Related

- Supersedes #662, which is closed.
- Follow-up #667: always launch the metadata-named browser by path.
Until then, if Playwright's expected build cannot be read and the
installation ships a different build, the normal launch fails and is not
retried.

Please squash-merge.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants