Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
322aa0a
Decode Windows console output in its code page under Python 3.15's de…
JE-Chen Sep 25, 2026
b4d1adf
Map remote desktop input and the broadcast cursor through the capture…
JE-Chen Sep 25, 2026
5d0dbd9
Stamp host annotations with the frame's screen origin and draw them o…
JE-Chen Sep 25, 2026
734a418
Scale screen-coordinate conversions by the device pixel ratio everywh…
JE-Chen Sep 25, 2026
5d848a5
Keep semantic replay on the recorded point for unnamed or off-screen …
JE-Chen Sep 25, 2026
131672b
Contain OpenCV errors and check the unrounded budget in perceptual di…
JE-Chen Sep 25, 2026
75119b6
Read element geometry in every shape through one helper, refuse non-f…
JE-Chen Sep 25, 2026
c996186
Refuse secret:// in AC_resolve_ref and its MCP tools so secret values…
JE-Chen Sep 25, 2026
73441c4
Run nested action lists on the executor that is running them so devic…
JE-Chen Sep 25, 2026
3d7cffa
Name the region convention each Script Builder command actually reads…
JE-Chen Sep 25, 2026
ae6a603
Capture [left, top, right, bottom] regions on every monitor on Window…
JE-Chen Sep 25, 2026
827a5a1
Refuse NaN in drift tests, keep inferred schemas valid for their own …
JE-Chen Sep 25, 2026
0a7394e
Test NaN with math.isnan in json_contract rather than a self-comparis…
JE-Chen Sep 25, 2026
44b716a
Record that grab_logical on macOS returns Retina pixels and sees only…
JE-Chen Sep 25, 2026
a515e61
Grab macOS regions with scale_down so a Retina region stays in points…
JE-Chen Sep 25, 2026
7ee18e5
Read element geometry in any shape and match equal zero-area boxes, k…
JE-Chen Sep 25, 2026
7900099
Read every executor flag by its spelling through one as_bool, since b…
JE-Chen Sep 25, 2026
4258172
Read locate_all_image boxes in AC_grid_cell with box_format ltrb, cle…
JE-Chen Sep 25, 2026
b426e2d
Share one repair store per process without a db, store non-text appro…
JE-Chen Sep 25, 2026
70be5dc
Pin sys.platform in the offscreen screen probes so macOS runners expe…
JE-Chen Sep 25, 2026
322ca5c
Match 16-bit and float images in 8 bits and skip unscorable scales, c…
JE-Chen Sep 26, 2026
655ed44
Fail any headless test whose input reaches the real mouse or keyboard…
JE-Chen Sep 26, 2026
3f3fca0
Share named rate limiters so a reused name takes a new rate, keep the…
JE-Chen Sep 26, 2026
253bf52
Take the running loop with asyncio.get_running_loop() in the WebRTC c…
JE-Chen Sep 26, 2026
89efd92
Answer every MCP tools/call whatever the tool raises, answer plain PO…
JE-Chen Sep 26, 2026
3a483f0
Pin sys.platform in the default field-entry plan test, which macOS ru…
JE-Chen Sep 26, 2026
469ad8c
Refuse a 0 ms auto-click interval, show framework and decode errors i…
JE-Chen Sep 26, 2026
dc94552
Enumerate USB devices off the GUI thread and only once shown, share t…
JE-Chen Sep 26, 2026
f3d53d9
Skip the tabs-menu leak test where qt_material is not installed, and …
JE-Chen Sep 26, 2026
c299bcc
Call the VLM off the GUI thread, and show each engine's own running s…
JE-Chen Sep 26, 2026
8732021
Match JSON Schema patterns as ECMA-262 does, so ^\d+$ no longer accep…
JE-Chen Sep 26, 2026
25c9bc1
Decode a JSONPath surrogate pair written as two escapes into one char…
JE-Chen Sep 26, 2026
9011dc7
Give the fake accessibility backend its base's signatures and take Pa…
JE-Chen Sep 26, 2026
890d29d
Count the Age header in HTTP cache freshness, keep the first of dupli…
JE-Chen Sep 26, 2026
d15f841
Refuse an empty or non-string JWT key, refuse a token whose aud the p…
JE-Chen Sep 26, 2026
9a905b0
Resolve a percent-encoded ../ in URL canonicalisation, never turn a /…
JE-Chen Sep 26, 2026
afa121f
Read cookie Expires with the RFC 6265 date algorithm, let the last va…
JE-Chen Sep 26, 2026
5b18e66
Parse Link headers with the RFC 8288 Appendix B algorithm, so a < in …
JE-Chen Sep 26, 2026
6dad1b9
Keep a tracestate value's leading spaces, discard members that break …
JE-Chen Sep 26, 2026
abe78f9
Keep a .env value that starts with #, keep a multi-line value's trail…
JE-Chen Sep 26, 2026
83c8136
Buffer an unterminated SSE line in pieces instead of re-splitting the…
JE-Chen Sep 26, 2026
d2b25d8
Validate a multipart boundary, refuse or redraw one a part contains s…
JE-Chen Sep 26, 2026
3dbc839
Leave untranslated entries out of a compiled .mo, as msgfmt does, so …
JE-Chen Sep 26, 2026
9765591
Count a yearly BYDAY ordinal within the year alongside BYMONTHDAY, ke…
JE-Chen Sep 26, 2026
a910155
Encode a bytes attribute as OTLP bytesValue instead of its Python rep…
JE-Chen Sep 26, 2026
da7332a
Give French its CLDR ordinals, match a locale by language and fall ba…
JE-Chen Sep 26, 2026
9afe453
Pin ruff's rule set in pyproject.toml so a ruff upgrade does not chan…
JE-Chen Sep 26, 2026
feef378
Run AC_web_run's documented form, record WebRunner failures, gate thr…
JE-Chen Sep 30, 2026
bcc8042
Pin the AC commands WebRunner's native WR_ac_* commands send
JE-Chen Sep 30, 2026
6062510
Progress: record the intermittent Python 3.10 segfault in test_usb_ac…
JE-Chen Sep 30, 2026
fb49e32
Add write_secret / AC_write_secret: type a password without logging, …
JE-Chen Oct 1, 2026
3cd0906
Gate AC_add_package_to_executor behind a package allowlist so an acti…
JE-Chen Oct 1, 2026
c872d98
Name write_secret's record mask so bandit stops reading it as a hardc…
JE-Chen Oct 1, 2026
b1c744d
Merge pull request #493 from Integration-Automation/feat/secret-typing
JE-Chen Oct 1, 2026
6b20ab8
Merge feat/coverage-to-80 into feat/package-gate: keep write_secret a…
JE-Chen Oct 1, 2026
ce616be
Merge pull request #492 from Integration-Automation/feat/package-gate
JE-Chen Oct 1, 2026
ded3425
Publish je_auto_control_dev from CI on a tested push to dev, built fr…
JE-Chen Oct 1, 2026
1f79fb9
Split the matrix-square assertion in test_dev_release so each failure…
JE-Chen Oct 1, 2026
9dde5c8
Merge pull request #494 from Integration-Automation/feat/dev-channel-…
JE-Chen Oct 1, 2026
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
  •  
  •  
  •  
145 changes: 145 additions & 0 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: AutoControl Dev CI

# The dev channel. A push or pull request to dev runs the headless suite, and
# a push that passes is then built from dev.toml and published to PyPI as
# je_auto_control_dev (the publish-dev job). main has its own workflows:
# quality.yml gates it and stable.yml publishes je_auto_control.

on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]

permissions:
contents: read

jobs:
pytest-headless:
# The same suite, install steps and command as the pytest-headless job of
# quality.yml, without the coverage floor: that ratchet belongs to main.
# Every square here is one quality.yml also runs. Each operating system
# runs once, because the facade imports a different backend on each, and
# Windows runs both ends of the supported Python range. The full nine-way
# matrix runs on the pull request that takes dev to main.
runs-on: ${{ matrix.os }}
timeout-minutes: 30 # about 3x a square of the same suite in quality.yml
strategy:
fail-fast: false
matrix:
include:
- { os: windows-2022, python-version: "3.10" }
- { os: windows-2022, python-version: "3.14" }
- { os: ubuntu-22.04, python-version: "3.14" }
- { os: macos-14, python-version: "3.10" }
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
cache: "pip"

# The X11 backend connects to a display at import time, opencv and
# PySide6 need libGL/glib, and Qt's platform plugin needs the xcb
# libraries: without them the suite fails at collection.
- name: Install X11 and Qt runtime libraries (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
xvfb xauth x11-utils \
libgl1 libegl1 libglib2.0-0 \
libxkbcommon-x11-0 libdbus-1-3 \
libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-sync1 \
libxcb-xfixes0 libxcb-xinerama0 libxcb-xkb1

# One command per step, each on a single line: a `run: |` block scalar
# swallows NOSONAR markers.
- name: Upgrade the installer
shell: bash
run: python -m pip install --upgrade pip wheel # NOSONAR githubactions:S8544 # reason: pip and wheel are the installer; pinning them here would pin the tool that applies the pins below

# The editable project, not dev_requirements.txt: that file installs the
# published je_auto_control_dev, whose copy of je_auto_control/ in
# site-packages would be tested instead of this checkout. The WebRTC
# extra is there because the tests of the WebRTC host skip without it.
- name: Install the project itself, with the WebRTC extra
shell: bash
run: pip install -e ".[webrtc]" # NOSONAR githubactions:S8544 githubactions:S8541 # reason: installs the checked-out project itself, so there is no upstream version to lock and no third-party setup script to run

- name: Install the test tooling
shell: bash
# The same line as quality.yml (test_dev_release.py compares them).
# Quoted: `--only-binary :all:` puts a colon-space inside the scalar.
run: "pip install --only-binary :all: ruff==0.15.22 bandit==1.9.4 pytest==9.1.1 pytest-timeout==2.4.0 pytest-rerunfailures==15.1 coverage==7.15.4 PySide6==6.11.1 radon==6.0.1"

# No path argument: the paths come from `testpaths` in pyproject.toml,
# and an argument would drop the flow_control tests. Linux runs under a
# real Xvfb because the X11 backend opens a display at import time.
- name: Run headless pytest suite
shell: bash
run: >-
${{ runner.os == 'Linux' && 'xvfb-run -a -s "-screen 0 1280x800x24"' || '' }}
python -m pytest -v --tb=short --timeout=120

publish-dev:
# A push to dev that passes the tests is built from dev.toml and uploaded
# when it is still the tip of dev and ships something the newest
# je_auto_control_dev does not. scripts/dev_release.py picks the version
# from PyPI, so nothing is committed back. The condition keeps the job off
# pull requests.
name: Publish je_auto_control_dev to PyPI
needs: [pytest-headless]
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
runs-on: ubuntu-latest
timeout-minutes: 15
concurrency:
group: publish-dev
cancel-in-progress: false

steps:
- uses: actions/checkout@v5
with:
persist-credentials: false

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

- name: Install build tooling
run: "pip install --only-binary :all: build==1.5.0 twine==6.2.0"

- name: Write pyproject.toml from dev.toml with the next version
run: python scripts/dev_release.py prepare

- name: Build distribution
run: python -m build

- name: Verify distribution metadata
run: python -m twine check dist/*

- name: Compare with the newest published wheel
id: compare
run: python scripts/dev_release.py changed dist

# A run that finishes after a newer push would otherwise publish older
# code as the newest release.
- name: Check that this commit is still the tip of dev
id: tip
run: |
tip="$(git ls-remote origin refs/heads/dev | cut -f1)"
if [ "$tip" = "$GITHUB_SHA" ]; then current=true; else current=false; fi
echo "current=$current" >> "$GITHUB_OUTPUT"

- name: Publish to PyPI
if: steps.compare.outputs.changed == 'true' && steps.tip.outputs.current == 'true'
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: python -m twine upload --non-interactive dist/*
Loading
Loading