pivot to Python: replace Kotlin/JVM with stdlib zipapp
Reasons stacked up:
- AV: unsigned JARs that auto-download binaries + upload files trigger
Windows Defender false-positives more often than Python scripts
invoked by code-signed python.exe.
- Qt UI option: PySide6 opens a path to a real Qt UI (matching Prism's
look) if needed later. JVM Qt bindings are abandoned.
- frazclient already needs Python; inlining as 'import cloud_sync' is
zero overhead vs the launcher always shelling out to java.
Implementation:
- cloud_sync package: cli.py (argparse), creds.py, scope.py,
restic.py (binary discovery + auto-download + sha256 verify),
sync.py (pull/push subprocess restic).
- pyproject.toml with hatchling backend; pip-installable.
- Makefile builds cloud-sync.pyz via python -m zipapp (~53 KB).
- 33 pytest tests, stdlib only on runtime.
- CI workflow runs pytest matrix (3.10/3.11/3.12) + builds pyz.
- DESIGN.md + README.md updated to reflect Python.
E2E verified against local restic-rest-server:
pull empty → push initial → rm -rf local → pull restores → modify+push
creates second snapshot → client forget --prune blocked by --append-only.
Throws away ~565 LOC of Kotlin (and 18 jar tests) committed earlier in
this same session. Net result is ~250 LOC Python + 33 tests = smaller
and more aligned with the rest of the stack.
This commit is contained in:
+30
-25
@@ -8,39 +8,46 @@ on:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
container:
|
||||
image: docker.io/gradle:8.10.2-jdk21
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
python: ["3.10", "3.11", "3.12"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- run: python -m pip install --upgrade pip
|
||||
- run: pip install -e .[test]
|
||||
- run: pytest -v
|
||||
|
||||
- name: Build fat jar
|
||||
run: gradle --no-daemon shadowJar
|
||||
|
||||
- name: Test
|
||||
run: gradle --no-daemon test
|
||||
|
||||
- name: Stash jar for release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
build-pyz:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
if: github.event_name == 'push'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- run: make build
|
||||
- if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cloud-sync-jar
|
||||
path: build/libs/cloud-sync-*.jar
|
||||
name: cloud-sync-pyz
|
||||
path: cloud-sync.pyz
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
needs: build-pyz
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: cloud-sync-jar
|
||||
path: build/libs/
|
||||
|
||||
name: cloud-sync-pyz
|
||||
- name: Publish release
|
||||
run: |
|
||||
gh_token="${{ secrets.RELEASE_TOKEN }}"
|
||||
@@ -51,9 +58,7 @@ jobs:
|
||||
-d "{\"tag_name\":\"${tag}\",\"name\":\"${tag}\",\"draft\":false,\"prerelease\":false}" \
|
||||
"${GITEA_SERVER_URL}/api/v1/repos/${{ gitea.event.repository.full_name }}/releases" > /tmp/release.json
|
||||
release_id=$(jq -r .id /tmp/release.json)
|
||||
for jar in build/libs/cloud-sync-*.jar; do
|
||||
curl -sS -X POST \
|
||||
-H "Authorization: token ${gh_token}" \
|
||||
-F "attachment=@${jar}" \
|
||||
"${GITEA_SERVER_URL}/api/v1/repos/${{ gitea.event.repository.full_name }}/releases/${release_id}/assets?name=$(basename $jar)"
|
||||
done
|
||||
curl -sS -X POST \
|
||||
-H "Authorization: token ${gh_token}" \
|
||||
-F "attachment=@cloud-sync.pyz" \
|
||||
"${GITEA_SERVER_URL}/api/v1/repos/${{ gitea.event.repository.full_name }}/releases/${release_id}/assets?name=cloud-sync.pyz"
|
||||
|
||||
Reference in New Issue
Block a user