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
f9bc431
docs: point progress.md at the workspace items still open
JE-Chen Sep 25, 2026
d8f4a14
Wait 7 days before Dependabot proposes a new release
JE-Chen Sep 25, 2026
0450d50
docs: CLAUDE.md: look up SonarCloud/Codacy findings through their API…
JE-Chen Sep 25, 2026
86aecda
docs: CLAUDE.md: the Codacy project token only works for its own proj…
JE-Chen Sep 25, 2026
b68e88d
Declare the MIT license as an SPDX expression in both channels
JE-Chen Sep 25, 2026
8a9ac1e
List Python 3.11 to 3.14 in the classifiers, as CI tests them
JE-Chen Sep 25, 2026
fec7fdf
Format the classifier test with ruff
JE-Chen Sep 25, 2026
fe50703
Give every workflow job a timeout
JE-Chen Oct 1, 2026
e35e100
Pass ruff B905 in the workflow-timeout test
JE-Chen Oct 1, 2026
5eefb53
refactor: build the registry, executor pipeline and helpers on je_act…
JE-Chen Oct 1, 2026
4fa2e39
build: install je_action_core from PyPI instead of the GitHub pin
JE-Chen Oct 1, 2026
1a6a468
test: guard that no action command loads packages, which keeps the pa…
JE-Chen Oct 1, 2026
3057b34
test: pin the TCP server's wire replies before it moves to je_action_…
JE-Chen Oct 1, 2026
8269caa
refactor: run the TCP server on je_action_core's secret-header handler
JE-Chen Oct 1, 2026
15e481f
ci: publish automation_file_dev from a tested push to dev that change…
JE-Chen Oct 1, 2026
8c565dd
build: stop the wheels installing the test suite as a top-level package
JE-Chen Oct 1, 2026
03fd4d7
build: keep the test suite out of the source distributions
JE-Chen Oct 1, 2026
78cfc1d
ci: install hash-locked build tools in the publish jobs
JE-Chen Oct 1, 2026
a0dd11f
ci: build with the locked setuptools in the publish jobs
JE-Chen Oct 1, 2026
9f487c3
feat: add the universal storage layer with local and memory backends
JE-Chen Oct 8, 2026
f20a150
feat: put S3 and Azure Blob behind the storage layer
JE-Chen Oct 8, 2026
2cfb09f
feat: add FA_storage actions for the storage layer
JE-Chen Oct 8, 2026
2cd7343
refactor: let a storage backend instance carry its own scheme and cap…
JE-Chen Oct 8, 2026
c6f4968
fix: keep version directories short enough for long source paths
JE-Chen Oct 8, 2026
7ae82f9
feat: add streams and directory trees to the storage layer
JE-Chen Oct 8, 2026
16e5eab
feat: add the event model, the event bus and storage observers
JE-Chen Oct 8, 2026
810e507
docs: describe FA_copy_between on the cloud pages instead of a FA_cro…
JE-Chen Oct 8, 2026
c394651
docs: drop drive:// from the architecture diagrams
JE-Chen Oct 8, 2026
43432c7
build: move the backend SDKs and the GUI toolkit under extras
JE-Chen Oct 8, 2026
e90fc87
test: add denied and transient failure cases to the storage contract
JE-Chen Oct 8, 2026
22f9cde
feat: add a storage subcommand to the CLI
JE-Chen Oct 8, 2026
c58b5b3
feat: add storage adapters for eight more backends
JE-Chen Oct 8, 2026
d9416a6
feat: add IntegrityMonitor 2.0
JE-Chen Oct 8, 2026
80f0e0d
feat: add the notification router and audit schema v2
JE-Chen Oct 8, 2026
bfa6f19
feat: add the pipeline runtime
JE-Chen Oct 8, 2026
821df87
feat: add integrity, pipeline and audit subcommands to the CLI
JE-Chen Oct 8, 2026
ba7c455
refactor: run copy_between on the storage layer
JE-Chen Oct 8, 2026
41f3782
docs: add the public API and deprecation policy
JE-Chen Oct 8, 2026
6910e4d
test: add integration tests against real services and their workflow
JE-Chen Oct 8, 2026
541adc9
ci: let a release raise MINOR or MAJOR, and check the package build
JE-Chen Oct 8, 2026
036ebfa
docs: correct the README line that said the backends are installed by…
JE-Chen Oct 8, 2026
240de15
test: add metadata cases to the storage contract
JE-Chen Oct 8, 2026
089c7d7
docs: add the production deployment guide
JE-Chen Oct 8, 2026
e998011
feat: add semantic MCP tools with a permission model
JE-Chen Oct 8, 2026
805dbf0
docs: state one positioning in the READMEs, the manuals and the metadata
JE-Chen Oct 8, 2026
ee437d0
feat: add scheduler v2
JE-Chen Oct 8, 2026
87d8908
feat: add the application layer and UI 2.0
JE-Chen Oct 8, 2026
f446ef9
docs: add the migration guide
JE-Chen Oct 8, 2026
0757995
test: stop an audit test from matching its content in random ids
JE-Chen Oct 8, 2026
d0f945a
fix: correct what the first run against real services and macOS showed
JE-Chen Oct 8, 2026
d578a0b
chore: answer the static-analysis findings of the pull request
JE-Chen Oct 8, 2026
5bff680
chore: shorten the scanner markers and name the S3 test server that i…
JE-Chen Oct 8, 2026
b279492
docs: record the first CI runs of the pull request and what is left
JE-Chen Oct 8, 2026
7ffd7ce
Lock lint and integration dependencies and resolve main review findings
JE-Chen Oct 8, 2026
1f416ad
Freeze the limiter clock while testing concurrent burst capacity
JE-Chen Oct 8, 2026
1a2718f
Close the shared Qt application before interpreter shutdown
JE-Chen Oct 8, 2026
58b6bc8
Keep GUI installs on the verified Qt 6.11 series
JE-Chen Oct 8, 2026
ef8c06f
Archive the completed main pull request validation
JE-Chen Oct 8, 2026
4d51cb9
Record the integrated PyBreeze dependency compatibility fix
JE-Chen Oct 8, 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
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# Auto detect text files and perform LF normalization
* text=auto
# Shell scripts run under bash on Linux runners, which does not accept CRLF.
*.sh text eol=lf
13 changes: 12 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,27 @@
version: 2
updates:
- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
# "/" holds requirements.txt and dev_requirements.txt. .github/requirements
# holds the hash-locked tools of the publish jobs (publish.in, publish.txt).
directories: # Locations of package manifests
- "/"
- "/.github/requirements"
# Updates belong on dev: main is the released branch and merging into it
# publishes, so a PR opened against main just sits there.
target-branch: "dev"
schedule:
interval: "daily"
# A new release waits 7 days before Dependabot proposes it, so a
# compromised version is more likely to be found and yanked first.
# Dependabot's own default is 3 days. Security updates are not delayed.
cooldown:
default-days: 7
# Workflow actions are pinned to commit SHAs with the version as a comment
# (test_workflow_actions.py); Dependabot moves both together.
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "dev"
schedule:
interval: "weekly"
cooldown:
default-days: 7
33 changes: 33 additions & 0 deletions .github/requirements/integration.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Python 3.12 integration dependencies, locked for all runner platforms.
# Regenerate: uv pip compile --universal --python-version 3.12 --generate-hashes
# --only-binary :all: --exclude-newer 2026-10-02T00:00:00Z
# .github/requirements/integration.in -o .github/requirements/integration.txt
setuptools>=77
wheel
requests>=2.31.0
tqdm>=4.66.0
watchdog>=4.0.0
cryptography>=50.0.0
prometheus_client>=0.26.0
defusedxml>=0.7.1
je_action_core>=0.0.2
PyYAML>=6.0.3
tzdata>=2024.1; platform_system == 'Windows'
opentelemetry-api>=1.44.0
opentelemetry-sdk>=1.44.0
tomli>=2.0.1; python_version<"3.11"
boto3>=1.34.0
azure-storage-blob>=12.19.0
google-api-python-client>=2.100.0
google-auth-httplib2>=0.2.0
google-auth-oauthlib>=1.2.0
dropbox>=11.36.2
paramiko>=3.4.0
smbprotocol>=1.13.0
fsspec>=2024.2.0
msal>=1.39.0
boxsdk>=10.15.0,<11
pyarrow>=25.0.1
PySide6>=6.11.2,<6.12
pytest>=8.0.0
pytest-cov>=5.0.0
1,152 changes: 1,152 additions & 0 deletions .github/requirements/integration.txt

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions .github/requirements/lint.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Regenerate with uv pip compile --generate-hashes --python-version 3.12
# --only-binary :all: --exclude-newer 2026-10-02T00:00:00Z
# .github/requirements/lint.in -o .github/requirements/lint.txt
ruff
mypy
je_action_core>=0.0.2
290 changes: 290 additions & 0 deletions .github/requirements/lint.txt

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions .github/requirements/publish.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Tools the two publish jobs run: publish-dev in ci-dev.yml and publish in publish.yml. Their version
# scripts use the standard library only. publish.txt is generated from this file, for the Python 3.12
# on Linux those jobs set up:
# uv pip compile .github/requirements/publish.in --generate-hashes --python-version 3.12 --python-platform x86_64-manylinux_2_28 --only-binary :all: --exclude-newer <a week ago, as 2026-09-24T00:00:00Z> -o .github/requirements/publish.txt
# --exclude-newer leaves out releases under a week old, the wait dependabot.yml sets.
build
twine
# The build backend. The jobs run `python -m build --no-isolation`, so the backend is this locked one
# and not whatever is newest on PyPI when the job runs. It must satisfy `build-system.requires` in
# stable.toml and dev.toml (tests/test_workflow_actions.py).
setuptools
472 changes: 472 additions & 0 deletions .github/requirements/publish.txt

Large diffs are not rendered by default.

131 changes: 127 additions & 4 deletions .github/workflows/ci-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ permissions:
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 15 # about 3x the slowest recent run, at least 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -24,8 +25,8 @@ jobs:
cache: pip
- name: Install tooling
run: |
python -m pip install --upgrade pip
pip install ruff mypy
# mypy reads the action engine types from the hash-locked tooling.
python -m pip install --require-hashes --only-binary :all: -r .github/requirements/lint.txt
- name: Ruff check
run: ruff check automation_file tests
- name: Ruff format check
Expand All @@ -36,6 +37,7 @@ jobs:
pytest:
needs: lint
runs-on: windows-latest
timeout-minutes: 15 # about 3x the slowest recent run, at least 15
strategy:
fail-fast: false
matrix:
Expand All @@ -53,8 +55,8 @@ jobs:
run: |
python -m pip install --upgrade pip wheel
Copy-Item dev.toml pyproject.toml -Force
pip install -e .
pip install pytest pytest-cov
# Every extra, so every backend's tests run. The minimal job runs without any.
pip install -e ".[all,test]"
- name: Run pytest with coverage
run: python -m pytest tests/ -v --tb=short --cov=automation_file --cov-report=term-missing --cov-report=xml
- name: Upload coverage artifact
Expand All @@ -63,3 +65,124 @@ jobs:
with:
name: coverage-xml
path: coverage.xml

minimal:
# The base install: no cloud SDK and no GUI toolkit. The tests of a backend whose extra is
# missing skip; everything else, the import guard included, has to pass.
needs: lint
runs-on: windows-latest
timeout-minutes: 15 # no run yet: the floor of 15 minutes, to revisit after the first runs
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip
- name: Install the base package
run: |
python -m pip install --upgrade pip wheel
Copy-Item dev.toml pyproject.toml -Force
pip install -e ".[test]"
- name: Run pytest
run: python -m pytest tests/ -v --tb=short

extras:
# Each extra on its own: it installs, and its backend's tests run with no other SDK present.
needs: lint
runs-on: windows-latest
timeout-minutes: 15 # no run yet: the floor of 15 minutes, to revisit after the first runs
strategy:
fail-fast: false
matrix:
extra: [ s3, azure, gdrive, dropbox, sftp, ftp, webdav, smb, fsspec, onedrive, box, parquet, gui ]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip
- name: Install the package with one extra
run: |
python -m pip install --upgrade pip wheel
Copy-Item dev.toml pyproject.toml -Force
pip install -e ".[${{ matrix.extra }},test]"
- name: Run pytest
run: python -m pytest tests/ -v --tb=short

package:
# The sdist and the wheel build from dev.toml and their metadata renders, before anything is
# merged. It gates nothing: the publish job builds again from the locked tools.
needs: lint
runs-on: ubuntu-latest
timeout-minutes: 15 # no run yet: the floor of 15 minutes, to revisit after the first runs
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip
- name: Build the distribution and check its metadata
run: |
# The locked, wheels-only tools the publish jobs build with.
python -m pip install --require-hashes --only-binary :all: -r .github/requirements/publish.txt
cp dev.toml pyproject.toml
python -m build --no-isolation
twine check dist/*

publish-dev:
# The dev channel. A push to dev that passes lint and the tests is built from dev.toml and uploaded
# when it is still the tip of dev and ships something the newest automation_file_dev does not.
# scripts/dev_release.py picks the version from PyPI, so nothing is committed back.
name: Publish automation_file_dev to PyPI
needs: [lint, pytest, minimal, extras]
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
runs-on: ubuntu-latest
timeout-minutes: 15 # about 3x the slowest recent run, at least 15
concurrency:
group: publish-dev
cancel-in-progress: false
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
# This job holds the PyPI token, so its tools are hash-locked and wheels only.
# .github/requirements/publish.in says how publish.txt is generated.
- name: Install build tools
run: |
python -m pip install --require-hashes --only-binary :all: -r .github/requirements/publish.txt
- name: Write pyproject.toml from dev.toml with the next version
run: python scripts/dev_release.py prepare
# --no-isolation: the backend is the setuptools locked in publish.txt, not a fresh download.
- name: Build distribution
run: python -m build --no-isolation
- 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/*
82 changes: 78 additions & 4 deletions .github/workflows/ci-stable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ permissions:
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 15 # about 3x the slowest recent run, at least 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -24,8 +25,8 @@ jobs:
cache: pip
- name: Install tooling
run: |
python -m pip install --upgrade pip
pip install ruff mypy
# mypy reads the action engine types from the hash-locked tooling.
python -m pip install --require-hashes --only-binary :all: -r .github/requirements/lint.txt
- name: Ruff check
run: ruff check automation_file tests
- name: Ruff format check
Expand All @@ -36,6 +37,7 @@ jobs:
pytest:
needs: lint
runs-on: windows-latest
timeout-minutes: 15 # about 3x the slowest recent run, at least 15
strategy:
fail-fast: false
matrix:
Expand All @@ -53,8 +55,8 @@ jobs:
run: |
python -m pip install --upgrade pip wheel
Copy-Item stable.toml pyproject.toml -Force
pip install -e .
pip install pytest pytest-cov
# Every extra, so every backend's tests run. The minimal job runs without any.
pip install -e ".[all,test]"
- name: Run pytest with coverage
run: python -m pytest tests/ -v --tb=short --cov=automation_file --cov-report=term-missing --cov-report=xml
- name: Upload coverage artifact
Expand All @@ -63,3 +65,75 @@ jobs:
with:
name: coverage-xml
path: coverage.xml

minimal:
# The base install: no cloud SDK and no GUI toolkit. The tests of a backend whose extra is
# missing skip; everything else, the import guard included, has to pass.
needs: lint
runs-on: windows-latest
timeout-minutes: 15 # no run yet: the floor of 15 minutes, to revisit after the first runs
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip
- name: Install the base package
run: |
python -m pip install --upgrade pip wheel
Copy-Item stable.toml pyproject.toml -Force
pip install -e ".[test]"
- name: Run pytest
run: python -m pytest tests/ -v --tb=short

extras:
# Each extra on its own: it installs, and its backend's tests run with no other SDK present.
needs: lint
runs-on: windows-latest
timeout-minutes: 15 # no run yet: the floor of 15 minutes, to revisit after the first runs
strategy:
fail-fast: false
matrix:
extra: [ s3, azure, gdrive, dropbox, sftp, ftp, webdav, smb, fsspec, onedrive, box, parquet, gui ]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip
- name: Install the package with one extra
run: |
python -m pip install --upgrade pip wheel
Copy-Item stable.toml pyproject.toml -Force
pip install -e ".[${{ matrix.extra }},test]"
- name: Run pytest
run: python -m pytest tests/ -v --tb=short

package:
# The sdist and the wheel build from stable.toml and their metadata renders, before anything is
# merged. It gates nothing: the publish job builds again from the locked tools.
needs: lint
runs-on: ubuntu-latest
timeout-minutes: 15 # no run yet: the floor of 15 minutes, to revisit after the first runs
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip
- name: Build the distribution and check its metadata
run: |
# The locked, wheels-only tools the publish jobs build with.
python -m pip install --require-hashes --only-binary :all: -r .github/requirements/publish.txt
cp stable.toml pyproject.toml
python -m build --no-isolation
twine check dist/*
Loading
Loading