gflow-cli 0.4.0a2__tar.gz → 0.5.0a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/.claude/commands/release.md +21 -10
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/.github/workflows/ci.yml +8 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/.github/workflows/release.yml +5 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/.gitignore +7 -0
- gflow_cli-0.5.0a1/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +38 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/CHANGELOG.md +90 -0
- gflow_cli-0.5.0a1/CONFIGURATION.md +68 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/PKG-INFO +22 -10
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/README.md +21 -9
- gflow_cli-0.5.0a1/RELEASE.md +97 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/AUTHENTICATION.md +1 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/INDEX.md +2 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/SECURITY.md +1 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/USAGE.md +61 -0
- gflow_cli-0.5.0a1/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +123 -0
- gflow_cli-0.5.0a1/examples/README.md +57 -0
- gflow_cli-0.5.0a1/examples/batch_from_config.py +99 -0
- gflow_cli-0.5.0a1/examples/sample_config.json +18 -0
- gflow_cli-0.5.0a1/examples/single_image_t2i.py +135 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/pyproject.toml +5 -1
- gflow_cli-0.5.0a1/scripts/diag_capture_flow_traffic.py +125 -0
- gflow_cli-0.5.0a1/scripts/diag_recaptcha_mint.py +77 -0
- gflow_cli-0.5.0a1/scripts/smoke_real_chrome_image.py +416 -0
- gflow_cli-0.5.0a1/scripts/smoke_worker_style.py +415 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/__init__.py +1 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/api/client.py +100 -57
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/api/image.py +13 -3
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/__init__.py +83 -0
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/_common.py +105 -0
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/_fingerprint.py +140 -0
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/base.py +59 -0
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/experimental/__init__.py +28 -0
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/experimental/bearer.py +341 -0
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +311 -0
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/experimental/sapisidhash.py +301 -0
- gflow_cli-0.5.0a1/src/gflow_cli/api/transports/ui_automation.py +611 -0
- gflow_cli-0.5.0a1/src/gflow_cli/browser_manager.py +633 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/cli.py +2 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/cli_image.py +49 -4
- gflow_cli-0.5.0a1/src/gflow_cli/cli_run.py +466 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/config.py +12 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/errors.py +49 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tasks/lessons.md +79 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_client.py +138 -0
- gflow_cli-0.5.0a1/tests/api/test_client_image.py +827 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_image.py +19 -10
- gflow_cli-0.5.0a1/tests/api/transports/test_base.py +41 -0
- gflow_cli-0.5.0a1/tests/api/transports/test_bearer.py +443 -0
- gflow_cli-0.5.0a1/tests/api/transports/test_common.py +203 -0
- gflow_cli-0.5.0a1/tests/api/transports/test_evaluate_fetch.py +463 -0
- gflow_cli-0.5.0a1/tests/api/transports/test_factory.py +60 -0
- gflow_cli-0.5.0a1/tests/api/transports/test_fingerprint.py +118 -0
- gflow_cli-0.5.0a1/tests/api/transports/test_sapisidhash.py +404 -0
- gflow_cli-0.5.0a1/tests/api/transports/test_ui_automation.py +996 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/cli/test_cli_image.py +119 -0
- gflow_cli-0.5.0a1/tests/cli/test_cli_run.py +421 -0
- gflow_cli-0.5.0a1/tests/e2e/__init__.py +0 -0
- gflow_cli-0.5.0a1/tests/e2e/test_transports_e2e.py +317 -0
- gflow_cli-0.5.0a1/tests/features/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/features/test_image_steps.py +3 -1
- gflow_cli-0.5.0a1/tests/smoke/__init__.py +0 -0
- gflow_cli-0.5.0a1/tests/smoke/test_real_flow.py +88 -0
- gflow_cli-0.5.0a1/tests/test_browser_manager.py +1543 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_errors.py +28 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_smoke.py +1 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/uv.lock +7 -1
- gflow_cli-0.4.0a2/tests/api/test_client_image.py +0 -799
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/.claude/README.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/.env.template +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/.gitattributes +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/CLAUDE.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/CONTRIBUTING.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/DISCLAIMER.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/KNOWN_ISSUES.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/LICENSE +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/PLAN.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/ARCHITECTURE.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/CONFIGURATION.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/USER_GUIDE.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/samples/README.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/samples/captured/01_upload_image.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/samples/captured/04_archive_workflow.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/samples/captured/05_createProject.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/samples/captured/06_batchGenerateImages.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/scripts/smoke_e2e.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/scripts/smoke_image.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/skills/README.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/skills/gflow-cli/SKILL.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/__main__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/_cli_helpers.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/api/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/api/_retry.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/api/dto.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/api/recaptcha.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/api/routes.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/api/video.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/auth.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/cli_video.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/manifest.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/observability.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/paths.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/src/gflow_cli/profile_store.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_client_generate_video.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_concurrency.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_dto.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_image_dto.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_recaptcha.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_retry.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_routes.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/api/test_video.py +0 -0
- {gflow_cli-0.4.0a2/tests/cli → gflow_cli-0.5.0a1/tests/api/transports}/__init__.py +0 -0
- {gflow_cli-0.4.0a2/tests/features → gflow_cli-0.5.0a1/tests/cli}/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/cli/test_error_handling.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/cli/test_helpers.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/conftest.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/features/auth.feature +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/features/conftest.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/features/image.feature +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/features/test_auth_steps.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/features/test_step_collision_guard.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/features/test_video_steps.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/features/video.feature +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_auth.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_cli_video.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_config.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_manifest.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_observability.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_paths.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.5.0a1}/tests/test_profile_store.py +0 -0
|
@@ -9,8 +9,8 @@ You are about to release a new version of `gflow-cli`. Follow this sequence verb
|
|
|
9
9
|
## Inputs
|
|
10
10
|
|
|
11
11
|
Ask the user (if not already provided):
|
|
12
|
-
1. **Version** — the new
|
|
13
|
-
2. **Pre-release?** — `0.
|
|
12
|
+
1. **Version** — the new version (e.g. `0.4.0`, `0.4.0a3`, `1.0.0rc1`). Use PEP 440 prerelease suffixes (`aN`, `bN`, `rcN`) for Python package releases. If they don't know, look at the latest entry in `CHANGELOG.md` `[Unreleased]` and propose the next bump (PATCH for fixes only, MINOR for new features, MAJOR for breaks).
|
|
13
|
+
2. **Pre-release?** — prerelease versions such as `0.4.0a3` should stay marked as GitHub prereleases. Only the user can say when a release line is ready for the stable tag, such as `0.4.0`.
|
|
14
14
|
|
|
15
15
|
## Sequence
|
|
16
16
|
|
|
@@ -41,7 +41,17 @@ Ask the user (if not already provided):
|
|
|
41
41
|
version = "<NEW_VERSION>"
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
5. **
|
|
44
|
+
5. **Bump package version** in `src/gflow_cli/__init__.py`:
|
|
45
|
+
```python
|
|
46
|
+
__version__ = "<NEW_VERSION>"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
6. **Update version assertion tests** if present:
|
|
50
|
+
```bash
|
|
51
|
+
rg -n "__version__|<OLD_VERSION>|version assertion" tests src pyproject.toml
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
7. **Update `CHANGELOG.md`:**
|
|
45
55
|
- Move all entries under `## [Unreleased]` to a new `## [<NEW_VERSION>] — YYYY-MM-DD` section.
|
|
46
56
|
- Leave `## [Unreleased]` empty.
|
|
47
57
|
- Update the link footer:
|
|
@@ -50,24 +60,24 @@ Ask the user (if not already provided):
|
|
|
50
60
|
[<NEW_VERSION>]: https://github.com/ffroliva/gflow-cli/releases/tag/v<NEW_VERSION>
|
|
51
61
|
```
|
|
52
62
|
|
|
53
|
-
|
|
63
|
+
8. **Commit the release prep.**
|
|
54
64
|
```bash
|
|
55
|
-
git add pyproject.toml CHANGELOG.md
|
|
56
|
-
git commit -m "release: v<NEW_VERSION>"
|
|
65
|
+
git add pyproject.toml src/gflow_cli/__init__.py CHANGELOG.md tests
|
|
66
|
+
git commit -m "chore(release): v<NEW_VERSION>"
|
|
57
67
|
```
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
9. **Tag.** PEP 440 prerelease tags include `aN` / `bN` / `rcN`:
|
|
60
70
|
```bash
|
|
61
71
|
git tag -a v<NEW_VERSION> -m "v<NEW_VERSION>"
|
|
62
72
|
```
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
10. **Push commit + tag.**
|
|
65
75
|
```bash
|
|
66
76
|
git push origin main
|
|
67
77
|
git push origin v<NEW_VERSION>
|
|
68
78
|
```
|
|
69
79
|
|
|
70
|
-
|
|
80
|
+
11. **Report.** Tell the user:
|
|
71
81
|
- The pushed tag triggers `.github/workflows/release.yml`.
|
|
72
82
|
- Watch <https://github.com/ffroliva/gflow-cli/actions> for the release workflow.
|
|
73
83
|
- On success: PyPI publish + GitHub Release with auto-generated notes.
|
|
@@ -82,5 +92,6 @@ Ask the user (if not already provided):
|
|
|
82
92
|
|
|
83
93
|
## See also
|
|
84
94
|
|
|
85
|
-
- [
|
|
95
|
+
- [RELEASE.md](../../RELEASE.md) — full release protocol, prerelease policy, and checklist
|
|
96
|
+
- [README § Releases](../../README.md#releases) — short release policy & cadence
|
|
86
97
|
- [PLAN § Phase 5](../../PLAN.md#phase-5--public-alpha-release-on-pypi) — first-release exit criteria
|
|
@@ -32,4 +32,11 @@ jobs:
|
|
|
32
32
|
run: uv run pyright src
|
|
33
33
|
|
|
34
34
|
- name: Test (smoke only)
|
|
35
|
-
|
|
35
|
+
# e2e tests (tests/e2e/) require a logged-in `denon82` Chromium profile
|
|
36
|
+
# and live Flow auth — never runnable in CI. They self-mark with
|
|
37
|
+
# `pytestmark = pytest.mark.e2e` (file-level) and are opt-in via
|
|
38
|
+
# `-m e2e` per their module docstring. `live` marker is reserved for
|
|
39
|
+
# `GFLOW_LIVE=1` tests that hit the real Flow API. Both are excluded
|
|
40
|
+
# from the default smoke run; `tests/smoke/test_real_flow.py` already
|
|
41
|
+
# self-skips via `pytest.mark.skipif(GFLOW_E2E != "1")`.
|
|
42
|
+
run: uv run pytest -q -m "not e2e and not live"
|
|
@@ -50,4 +50,8 @@ jobs:
|
|
|
50
50
|
with:
|
|
51
51
|
generate_release_notes: true
|
|
52
52
|
files: dist/*
|
|
53
|
-
|
|
53
|
+
# Pre-release detection covers both conventions:
|
|
54
|
+
# - semver suffixes: v1.2.3-alpha1, v1.2.3-rc1, v1.2.3-beta1 (any '-' qualifies)
|
|
55
|
+
# - PEP 440 suffixes: v1.2.3a1, v1.2.3b1, v1.2.3rc1 (any 'a' / 'b' / 'rc')
|
|
56
|
+
# Stable tags like v1.2.3 contain none of these substrings.
|
|
57
|
+
prerelease: ${{ contains(github.ref_name, '-') || contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
|
|
@@ -48,6 +48,13 @@ tmp/
|
|
|
48
48
|
!tests/fixtures/**/*.png
|
|
49
49
|
samples/*.captured.json # sandbox-recorded API exchanges may contain PII
|
|
50
50
|
|
|
51
|
+
# Live Flow traffic captures — NEVER commit (contain real Bearer tokens / API keys).
|
|
52
|
+
# Diagnostic scripts MUST default-write here, NOT to samples/captured/.
|
|
53
|
+
# Sanitised reference samples (no secrets) can still live under samples/captured/.
|
|
54
|
+
tmp/captured/
|
|
55
|
+
samples/captured/flow_outgoing_*.jsonl
|
|
56
|
+
samples/captured/flow_outgoing_*.json
|
|
57
|
+
|
|
51
58
|
# Claude Code worktrees and lock files
|
|
52
59
|
.claude/worktrees/
|
|
53
60
|
.claude/scheduled_tasks.lock
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
created: 2026-05-11T11:34:56.295Z
|
|
3
|
+
title: Add project logo and docs site promotion plan
|
|
4
|
+
area: docs
|
|
5
|
+
files:
|
|
6
|
+
- README.md:18
|
|
7
|
+
- README.md:365
|
|
8
|
+
- RELEASE.md:1
|
|
9
|
+
- docs/INDEX.md:10
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Problem
|
|
13
|
+
|
|
14
|
+
The project is now public on GitHub and PyPI and has enough release/process
|
|
15
|
+
surface to benefit from a more polished presentation. The README was cleaned up
|
|
16
|
+
with working badges and a public `RELEASE.md`, but the next promotion step is
|
|
17
|
+
still undecided: whether to add a logo/social preview, whether to create a
|
|
18
|
+
GitHub Pages documentation site, and which static-docs stack to use.
|
|
19
|
+
|
|
20
|
+
Jekyll is available on GitHub Pages, but for this Python CLI project the better
|
|
21
|
+
default is likely MkDocs Material: it fits Markdown-heavy CLI docs, has search
|
|
22
|
+
and navigation, and can publish to GitHub Pages cleanly. This should wait until
|
|
23
|
+
after the current prerelease E2E validation, because the real launch gate is
|
|
24
|
+
runtime confidence, not site polish.
|
|
25
|
+
|
|
26
|
+
## Solution
|
|
27
|
+
|
|
28
|
+
After E2E validation, decide a small promotion package:
|
|
29
|
+
|
|
30
|
+
1. Add a simple project logo and GitHub social preview image.
|
|
31
|
+
2. Keep README as the landing page and make the first screen clear for users.
|
|
32
|
+
3. If docs navigation grows cramped, add a MkDocs Material site published to
|
|
33
|
+
GitHub Pages.
|
|
34
|
+
4. Avoid Jekyll unless the goal shifts toward a blog-style marketing site.
|
|
35
|
+
5. Add the star-history chart only after the repo has enough activity for the
|
|
36
|
+
graph to render as useful signal rather than empty axes.
|
|
37
|
+
6. Keep `RELEASE.md`, README release policy, and `.claude/commands/release.md`
|
|
38
|
+
in sync when the release process changes.
|
|
@@ -7,6 +7,96 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.0a1] — 2026-05-12
|
|
11
|
+
|
|
12
|
+
> **Pluggable image transport + JSON-described batch runs.** The image
|
|
13
|
+
> generation surface now ships a new default `ui_automation` transport —
|
|
14
|
+
> a Playwright-driven UI mimicry strategy validated end-to-end against
|
|
15
|
+
> real Flow on a Google AI Pro/Ultra profile. Three earlier HTTP
|
|
16
|
+
> transport strategies (`evaluate_fetch`, `bearer`, `sapisidhash`) move
|
|
17
|
+
> into a new `experimental/` subpackage; they remain importable for
|
|
18
|
+
> research but are hidden from the CLI by default. New top-level
|
|
19
|
+
> `gflow run --config <file>` command drives JSON-described sequential
|
|
20
|
+
> batches through one shared session.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **`UiAutomationTransport`** (`gflow_cli.api.transports.ui_automation`)
|
|
25
|
+
— new default transport. Drives the Flow editor on a logged-in
|
|
26
|
+
profile through a Playwright-managed persistent context (internal CDP
|
|
27
|
+
port; no externally-exposed debug port). Mirrors the validated
|
|
28
|
+
reference flow in `scripts/smoke_worker_style.py`.
|
|
29
|
+
- **`gflow run --config <file>`** — sequential JSON-described batch
|
|
30
|
+
command. Schema covers `profile`, `transport`, `output_dir`, and a
|
|
31
|
+
`prompts` list (1–50 entries) with per-prompt `text`,
|
|
32
|
+
`aspect_ratio`, `model`, `count`, and `output_filename`. Supports
|
|
33
|
+
`--continue-on-error` (default) and `--fail-fast` semantics; final
|
|
34
|
+
exit code is the max per-prompt exit code. ONE `FlowApiClient`
|
|
35
|
+
session wraps the whole loop so the browser/project persist across
|
|
36
|
+
prompts.
|
|
37
|
+
- **`examples/` directory** — three runnable scripts (`single_image_t2i.py`,
|
|
38
|
+
`batch_from_config.py`) + a copy-and-edit `sample_config.json` + an
|
|
39
|
+
index `examples/README.md`. All sanitised: no hardcoded profile
|
|
40
|
+
names, generic placeholder prompts, parameterised via `--profile` /
|
|
41
|
+
`$GFLOW_EXAMPLE_PROFILE`.
|
|
42
|
+
- **Opt-in real-Flow smoke test** at `tests/smoke/test_real_flow.py`,
|
|
43
|
+
gated by `GFLOW_E2E=1` + `GFLOW_E2E_PROFILE`. Runs the full
|
|
44
|
+
`UiAutomationTransport` flow against real Flow and asserts a
|
|
45
|
+
non-trivial PNG was written.
|
|
46
|
+
- **`EXPERIMENTAL_TRANSPORTS` constant** + **`transport_choices()`
|
|
47
|
+
helper** in `gflow_cli.api.transports`. The factory continues to
|
|
48
|
+
accept every registered key; the CLI `--transport` Choice list is
|
|
49
|
+
the gated surface (default = `ui_automation` only;
|
|
50
|
+
`GFLOW_CLI_EXPERIMENTAL_TRANSPORTS=1` expands to all four).
|
|
51
|
+
- **Download host allow-list** in `UiAutomationTransport._download`
|
|
52
|
+
(`googleusercontent.com`, `googleapis.com`, `google.com` suffix
|
|
53
|
+
match). `follow_redirects=False`. Prevents session cookies from
|
|
54
|
+
reaching a non-Google host through a malformed or compromised
|
|
55
|
+
`fifeUrl`.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- **Default `--transport` flag** flipped from `evaluate_fetch` to
|
|
60
|
+
`ui_automation` across `gflow image t2i`, `gflow image i2i`, and
|
|
61
|
+
`gflow image upload`. The change is transparent to existing scripts
|
|
62
|
+
unless they pinned `--transport evaluate_fetch` explicitly.
|
|
63
|
+
- **`evaluate_fetch` / `bearer` / `sapisidhash` strategies moved** to
|
|
64
|
+
`gflow_cli.api.transports.experimental.*`. Public registry keys
|
|
65
|
+
(the strings used by `make_transport()` and the
|
|
66
|
+
`GFLOW_CLI_TRANSPORT` env var) are unchanged. Import paths within
|
|
67
|
+
the package are the only user-visible delta.
|
|
68
|
+
- **Debug screenshots** captured by the strategy on `_enter_editor` /
|
|
69
|
+
`_send_prompt` failures are now **viewport-only**
|
|
70
|
+
(`full_page=False`) and emit a `WARNING` log line noting the file
|
|
71
|
+
may contain identifying information from the authenticated session.
|
|
72
|
+
|
|
73
|
+
### Fixed
|
|
74
|
+
|
|
75
|
+
- Listener-attach race in `generate_images`. The earlier
|
|
76
|
+
`asyncio.create_task(_capture_batch_response(page))` scheduled the
|
|
77
|
+
listener registration AFTER the next event-loop tick; on a busy
|
|
78
|
+
loop the prompt click could fire before the listener attached,
|
|
79
|
+
causing the capture to time out. Refactored into a synchronous
|
|
80
|
+
`_attach_batch_response_listener(page)` + an `async
|
|
81
|
+
_await_captured(captured, ...)`. No more orphaned task on partial
|
|
82
|
+
failure.
|
|
83
|
+
|
|
84
|
+
### Removed
|
|
85
|
+
|
|
86
|
+
- Dead `_extract_image_urls(response)` helper on
|
|
87
|
+
`UiAutomationTransport` and its five tests.
|
|
88
|
+
`generate_images` parses `body.media[]` directly through
|
|
89
|
+
`GeneratedImage.from_response_item`; the parallel helper was
|
|
90
|
+
unreachable.
|
|
91
|
+
|
|
92
|
+
### Documentation
|
|
93
|
+
|
|
94
|
+
- `BrowserManager` module docstring updated to make explicit that the
|
|
95
|
+
module is retained for research / non-Flow use, not on the
|
|
96
|
+
v0.5.0a1 image-generation critical path. No behavior change.
|
|
97
|
+
- README "Project status" table updated with v0.5.0a1 row.
|
|
98
|
+
- `docs/USAGE.md` gains a `gflow run` section.
|
|
99
|
+
|
|
10
100
|
## [0.4.0a2] — 2026-05-11
|
|
11
101
|
|
|
12
102
|
> **Documentation polish.** Same release surface as v0.4.0a1; this tag fixes
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# gflow-cli Configuration Reference
|
|
2
|
+
|
|
3
|
+
## Environment variables
|
|
4
|
+
|
|
5
|
+
| Env var | Default | Description |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| `GFLOW_CLI_HOME` | Platform data dir | Root directory for profiles and config. |
|
|
8
|
+
| `GFLOW_CLI_OUTPUT_DIR` | `~/Downloads/gflow-cli` | Where generated images and videos are saved. |
|
|
9
|
+
| `GFLOW_CLI_BROWSER` | `auto` | Browser mode. See **Browser mode** section below. |
|
|
10
|
+
| `CHROME_BINARY` | (autodetect) | Override Chrome binary path. Falls back to platform-standard locations. |
|
|
11
|
+
| `GFLOW_CLI_CONCURRENCY` | `4` | Maximum parallel API requests per batch. |
|
|
12
|
+
| `GFLOW_LIVE` | _(unset)_ | Set to `1` to enable live-API test markers (`@pytest.mark.live`). |
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Browser mode (D.2.3+)
|
|
17
|
+
|
|
18
|
+
| Env var | Default | Description |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `GFLOW_CLI_BROWSER` | `auto` | `auto` attaches to running Chrome via CDP or spawns detached; `fresh` launches new Playwright Chromium per call (legacy); `cdp:<port>` attaches to explicit CDP endpoint. |
|
|
21
|
+
| `CHROME_BINARY` | (autodetect) | Override Chrome binary path. Falls back to platform-standard locations. |
|
|
22
|
+
|
|
23
|
+
### When to use which
|
|
24
|
+
|
|
25
|
+
- **`auto`** (recommended): real Chrome fingerprint = highest reCAPTCHA risk score; persistent
|
|
26
|
+
across CLI invocations. First call spawns Chrome detached; subsequent calls attach via CDP.
|
|
27
|
+
- **`fresh`**: legacy single-shot Playwright Chromium. Use when you need a clean profile per call.
|
|
28
|
+
- **`cdp:<port>`**: connect to an already-running Chrome you spawned yourself
|
|
29
|
+
(e.g. with `--remote-debugging-port=9222`).
|
|
30
|
+
|
|
31
|
+
### Chrome binary autodetection order
|
|
32
|
+
|
|
33
|
+
1. `CHROME_BINARY` env var (checked first — always wins)
|
|
34
|
+
2. `shutil.which("chrome")` / `shutil.which("google-chrome")` / `shutil.which("chromium")`
|
|
35
|
+
3. Platform-standard paths:
|
|
36
|
+
- **Windows**: `C:\Program Files\Google\Chrome\Application\chrome.exe`,
|
|
37
|
+
`C:\Program Files (x86)\Google\Chrome\Application\chrome.exe`,
|
|
38
|
+
`%LOCALAPPDATA%\Google\Chrome\Application\chrome.exe`
|
|
39
|
+
- **macOS**: `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`
|
|
40
|
+
- **Linux**: `/usr/bin/google-chrome`, `/usr/bin/chromium`, `/usr/bin/chromium-browser`
|
|
41
|
+
|
|
42
|
+
If Chrome is not found, gflow-cli raises a `ConfigurationError` with an install hint.
|
|
43
|
+
|
|
44
|
+
### CDP port range
|
|
45
|
+
|
|
46
|
+
By default gflow-cli uses CDP port `9222`. If that port is occupied by a non-gflow Chrome,
|
|
47
|
+
it probes `9222–9229` until a free port is found. The chosen port is persisted in
|
|
48
|
+
`<profile_dir>/.gflow-cdp.lock` so subsequent calls reuse the same port.
|
|
49
|
+
|
|
50
|
+
If all 8 ports are occupied, a `ConfigurationError` is raised.
|
|
51
|
+
|
|
52
|
+
### Lockfile
|
|
53
|
+
|
|
54
|
+
`<profile_dir>/.gflow-cdp.lock` — JSON file containing `{pid, port, profile_name}`.
|
|
55
|
+
Written atomically (tmp + `os.link`, `O_CREAT|O_EXCL|O_NOFOLLOW`, mode `0o600`)
|
|
56
|
+
when Chrome is first spawned. Stale locks (PID no longer alive) are cleaned up
|
|
57
|
+
automatically on the next CLI invocation.
|
|
58
|
+
|
|
59
|
+
### Security note — localhost CDP trust model
|
|
60
|
+
|
|
61
|
+
The Chrome DevTools Protocol endpoint (`http://localhost:<port>/json/version`)
|
|
62
|
+
is **not authenticated**. Any process on the same machine that can reach
|
|
63
|
+
`localhost:9222` can drive the browser. gflow-cli treats a port owner that
|
|
64
|
+
matches our lockfile as trusted; an unmanaged Chrome on the same port is
|
|
65
|
+
attached with a `attached_to_unmanaged_chrome=true` warning logged.
|
|
66
|
+
|
|
67
|
+
**Do not run gflow-cli on a shared multi-user machine** where untrusted users
|
|
68
|
+
have shell access. Use a dedicated user account or a VM per worker.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gflow-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0a1
|
|
4
4
|
Summary: Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ffroliva/gflow-cli
|
|
6
6
|
Project-URL: Issues, https://github.com/ffroliva/gflow-cli/issues
|
|
@@ -69,7 +69,7 @@ Description-Content-Type: text/markdown
|
|
|
69
69
|
|
|
70
70
|
> ⚠️ **Not affiliated with Google.** Reverse-engineered from public Flow web traffic. Endpoints can change at any time. See full [DISCLAIMER](DISCLAIMER.md) before use.
|
|
71
71
|
|
|
72
|
-
📚 **Docs:** [INDEX](docs/INDEX.md) · [User Guide](docs/USER_GUIDE.md) · [Architecture](docs/ARCHITECTURE.md) · [Authentication](docs/AUTHENTICATION.md) · [Configuration](docs/CONFIGURATION.md) · [Usage](docs/USAGE.md) · [Security](docs/SECURITY.md) · [Known issues](KNOWN_ISSUES.md) · [Plan](PLAN.md) · [Changelog](CHANGELOG.md)
|
|
72
|
+
📚 **Docs:** [INDEX](docs/INDEX.md) · [User Guide](docs/USER_GUIDE.md) · [Architecture](docs/ARCHITECTURE.md) · [Authentication](docs/AUTHENTICATION.md) · [Configuration](docs/CONFIGURATION.md) · [Usage](docs/USAGE.md) · [Security](docs/SECURITY.md) · [Known issues](KNOWN_ISSUES.md) · [Release protocol](RELEASE.md) · [Plan](PLAN.md) · [Changelog](CHANGELOG.md)
|
|
73
73
|
🤖 **For AI agents:** [CLAUDE.md](CLAUDE.md) · [`.claude/`](.claude/README.md)
|
|
74
74
|
|
|
75
75
|
---
|
|
@@ -108,7 +108,7 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
|
|
|
108
108
|
|
|
109
109
|
## Project status
|
|
110
110
|
|
|
111
|
-
**v0.
|
|
111
|
+
**v0.5.0a1 — alpha.** Video (T2V/I2V/batch), image (T2I/I2I/upload), the new **`gflow run` JSON-batch command**, and the **`ui_automation` default transport** are functional end-to-end against a live Google AI Pro/Ultra Flow account. Three earlier HTTP transport strategies (`evaluate_fetch` / `bearer` / `sapisidhash`) move to an `experimental/` subpackage in this release; the production path is `ui_automation`.
|
|
112
112
|
|
|
113
113
|
| Milestone | Status |
|
|
114
114
|
|---|---|
|
|
@@ -122,7 +122,17 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
|
|
|
122
122
|
| Typed errors (RFC 9457 Problem Details) + per-class exit codes 3–7 | ✅ done (v0.4.0a2) |
|
|
123
123
|
| Retry / backoff + reCAPTCHA re-mint inside the retry loop | ✅ done (v0.4.0a2) |
|
|
124
124
|
| Structured logs (`structlog`, JSON on pipe) | ✅ done (v0.4.0a2) |
|
|
125
|
-
|
|
|
125
|
+
| Pluggable image transport + `ui_automation` default strategy | ✅ done (v0.5.0a1) |
|
|
126
|
+
| `gflow run --config <file>` sequential JSON batches | ✅ done (v0.5.0a1) |
|
|
127
|
+
| `examples/` directory with runnable single-image + batch scripts | ✅ done (v0.5.0a1) |
|
|
128
|
+
| Provider abstraction for official Veo 3.1 API | ⏳ planned (v0.6+) |
|
|
129
|
+
|
|
130
|
+
### What's new in v0.5.0a1
|
|
131
|
+
|
|
132
|
+
- `UiAutomationTransport` is now the default image-generation strategy — Playwright-driven UI mimicry against the Flow editor on a logged-in Pro/Ultra profile (no externally-exposed CDP debug port).
|
|
133
|
+
- New top-level `gflow run --config <file>` command for JSON-described sequential batches (1–50 prompts per file, `--continue-on-error` / `--fail-fast` modes). See [`docs/USAGE.md`](docs/USAGE.md#gflow-run) for the schema.
|
|
134
|
+
- Three runnable example scripts shipped under [`examples/`](examples/README.md) — copy and edit for your own pipelines.
|
|
135
|
+
- See the full [CHANGELOG](CHANGELOG.md#0501) for the security follow-ups (download host allow-list, viewport-only debug screenshots) and the listener-attach race fix.
|
|
126
136
|
|
|
127
137
|
---
|
|
128
138
|
|
|
@@ -376,17 +386,20 @@ Each `Provider` method has a corresponding test file under `tests/`. New routes
|
|
|
376
386
|
|
|
377
387
|
1. Update [`CHANGELOG.md`](CHANGELOG.md) with the version's changes (Keep-a-Changelog format).
|
|
378
388
|
2. Bump `version` in `pyproject.toml`.
|
|
379
|
-
3.
|
|
389
|
+
3. Bump `__version__` in `src/gflow_cli/__init__.py`.
|
|
390
|
+
4. Tag the commit:
|
|
380
391
|
```bash
|
|
381
|
-
git tag
|
|
382
|
-
git push origin
|
|
392
|
+
git tag v<version> # for example, v0.4.0 or v0.4.0a3
|
|
393
|
+
git push origin v<version>
|
|
383
394
|
```
|
|
384
|
-
|
|
395
|
+
5. The [`release.yml`](.github/workflows/release.yml) GitHub Action runs:
|
|
385
396
|
- Builds the wheel + sdist with `uv build`
|
|
386
397
|
- Publishes to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) — no API tokens stored
|
|
387
398
|
- Creates a GitHub Release with the changelog excerpt + built artifacts attached
|
|
388
399
|
|
|
389
|
-
|
|
400
|
+
PEP 440 prerelease tags (`vX.Y.ZaN`, `vX.Y.ZbN`, `vX.Y.ZrcN`) and hyphenated prerelease tags (`vX.Y.Z-alphaN`, `vX.Y.Z-betaN`, `vX.Y.Z-rcN`) auto-flag as prereleases on GitHub. Stable tags such as `v0.4.0` become full GitHub Releases. See [RELEASE.md](RELEASE.md) for the checklist and the prerelease/full-release policy.
|
|
401
|
+
|
|
402
|
+
Install prereleases explicitly with `pip install --pre gflow-cli` or `uvx --from "gflow-cli==0.4.0a2" gflow`.
|
|
390
403
|
|
|
391
404
|
---
|
|
392
405
|
|
|
@@ -422,6 +435,5 @@ Note that the **Google service** this tool talks to has its own terms (Google La
|
|
|
422
435
|
[](https://github.com/ffroliva/gflow-cli/commits/main)
|
|
423
436
|
[](https://github.com/ffroliva/gflow-cli)
|
|
424
437
|
[](https://pypi.org/project/gflow-cli/)
|
|
425
|
-
[](https://pypi.org/project/gflow-cli/)
|
|
426
438
|
|
|
427
439
|
If `gflow-cli` saves you time, please ⭐ the repo — it's the cheapest way to support the project.
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
> ⚠️ **Not affiliated with Google.** Reverse-engineered from public Flow web traffic. Endpoints can change at any time. See full [DISCLAIMER](DISCLAIMER.md) before use.
|
|
17
17
|
|
|
18
|
-
📚 **Docs:** [INDEX](docs/INDEX.md) · [User Guide](docs/USER_GUIDE.md) · [Architecture](docs/ARCHITECTURE.md) · [Authentication](docs/AUTHENTICATION.md) · [Configuration](docs/CONFIGURATION.md) · [Usage](docs/USAGE.md) · [Security](docs/SECURITY.md) · [Known issues](KNOWN_ISSUES.md) · [Plan](PLAN.md) · [Changelog](CHANGELOG.md)
|
|
18
|
+
📚 **Docs:** [INDEX](docs/INDEX.md) · [User Guide](docs/USER_GUIDE.md) · [Architecture](docs/ARCHITECTURE.md) · [Authentication](docs/AUTHENTICATION.md) · [Configuration](docs/CONFIGURATION.md) · [Usage](docs/USAGE.md) · [Security](docs/SECURITY.md) · [Known issues](KNOWN_ISSUES.md) · [Release protocol](RELEASE.md) · [Plan](PLAN.md) · [Changelog](CHANGELOG.md)
|
|
19
19
|
🤖 **For AI agents:** [CLAUDE.md](CLAUDE.md) · [`.claude/`](.claude/README.md)
|
|
20
20
|
|
|
21
21
|
---
|
|
@@ -54,7 +54,7 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
|
|
|
54
54
|
|
|
55
55
|
## Project status
|
|
56
56
|
|
|
57
|
-
**v0.
|
|
57
|
+
**v0.5.0a1 — alpha.** Video (T2V/I2V/batch), image (T2I/I2I/upload), the new **`gflow run` JSON-batch command**, and the **`ui_automation` default transport** are functional end-to-end against a live Google AI Pro/Ultra Flow account. Three earlier HTTP transport strategies (`evaluate_fetch` / `bearer` / `sapisidhash`) move to an `experimental/` subpackage in this release; the production path is `ui_automation`.
|
|
58
58
|
|
|
59
59
|
| Milestone | Status |
|
|
60
60
|
|---|---|
|
|
@@ -68,7 +68,17 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
|
|
|
68
68
|
| Typed errors (RFC 9457 Problem Details) + per-class exit codes 3–7 | ✅ done (v0.4.0a2) |
|
|
69
69
|
| Retry / backoff + reCAPTCHA re-mint inside the retry loop | ✅ done (v0.4.0a2) |
|
|
70
70
|
| Structured logs (`structlog`, JSON on pipe) | ✅ done (v0.4.0a2) |
|
|
71
|
-
|
|
|
71
|
+
| Pluggable image transport + `ui_automation` default strategy | ✅ done (v0.5.0a1) |
|
|
72
|
+
| `gflow run --config <file>` sequential JSON batches | ✅ done (v0.5.0a1) |
|
|
73
|
+
| `examples/` directory with runnable single-image + batch scripts | ✅ done (v0.5.0a1) |
|
|
74
|
+
| Provider abstraction for official Veo 3.1 API | ⏳ planned (v0.6+) |
|
|
75
|
+
|
|
76
|
+
### What's new in v0.5.0a1
|
|
77
|
+
|
|
78
|
+
- `UiAutomationTransport` is now the default image-generation strategy — Playwright-driven UI mimicry against the Flow editor on a logged-in Pro/Ultra profile (no externally-exposed CDP debug port).
|
|
79
|
+
- New top-level `gflow run --config <file>` command for JSON-described sequential batches (1–50 prompts per file, `--continue-on-error` / `--fail-fast` modes). See [`docs/USAGE.md`](docs/USAGE.md#gflow-run) for the schema.
|
|
80
|
+
- Three runnable example scripts shipped under [`examples/`](examples/README.md) — copy and edit for your own pipelines.
|
|
81
|
+
- See the full [CHANGELOG](CHANGELOG.md#0501) for the security follow-ups (download host allow-list, viewport-only debug screenshots) and the listener-attach race fix.
|
|
72
82
|
|
|
73
83
|
---
|
|
74
84
|
|
|
@@ -322,17 +332,20 @@ Each `Provider` method has a corresponding test file under `tests/`. New routes
|
|
|
322
332
|
|
|
323
333
|
1. Update [`CHANGELOG.md`](CHANGELOG.md) with the version's changes (Keep-a-Changelog format).
|
|
324
334
|
2. Bump `version` in `pyproject.toml`.
|
|
325
|
-
3.
|
|
335
|
+
3. Bump `__version__` in `src/gflow_cli/__init__.py`.
|
|
336
|
+
4. Tag the commit:
|
|
326
337
|
```bash
|
|
327
|
-
git tag
|
|
328
|
-
git push origin
|
|
338
|
+
git tag v<version> # for example, v0.4.0 or v0.4.0a3
|
|
339
|
+
git push origin v<version>
|
|
329
340
|
```
|
|
330
|
-
|
|
341
|
+
5. The [`release.yml`](.github/workflows/release.yml) GitHub Action runs:
|
|
331
342
|
- Builds the wheel + sdist with `uv build`
|
|
332
343
|
- Publishes to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) — no API tokens stored
|
|
333
344
|
- Creates a GitHub Release with the changelog excerpt + built artifacts attached
|
|
334
345
|
|
|
335
|
-
|
|
346
|
+
PEP 440 prerelease tags (`vX.Y.ZaN`, `vX.Y.ZbN`, `vX.Y.ZrcN`) and hyphenated prerelease tags (`vX.Y.Z-alphaN`, `vX.Y.Z-betaN`, `vX.Y.Z-rcN`) auto-flag as prereleases on GitHub. Stable tags such as `v0.4.0` become full GitHub Releases. See [RELEASE.md](RELEASE.md) for the checklist and the prerelease/full-release policy.
|
|
347
|
+
|
|
348
|
+
Install prereleases explicitly with `pip install --pre gflow-cli` or `uvx --from "gflow-cli==0.4.0a2" gflow`.
|
|
336
349
|
|
|
337
350
|
---
|
|
338
351
|
|
|
@@ -368,6 +381,5 @@ Note that the **Google service** this tool talks to has its own terms (Google La
|
|
|
368
381
|
[](https://github.com/ffroliva/gflow-cli/commits/main)
|
|
369
382
|
[](https://github.com/ffroliva/gflow-cli)
|
|
370
383
|
[](https://pypi.org/project/gflow-cli/)
|
|
371
|
-
[](https://pypi.org/project/gflow-cli/)
|
|
372
384
|
|
|
373
385
|
If `gflow-cli` saves you time, please ⭐ the repo — it's the cheapest way to support the project.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Release Protocol
|
|
2
|
+
|
|
3
|
+
This project publishes Python distributions to PyPI and GitHub Releases from
|
|
4
|
+
Git tags. The release workflow is `.github/workflows/release.yml`.
|
|
5
|
+
|
|
6
|
+
## Current Policy
|
|
7
|
+
|
|
8
|
+
- `0.x` versions are alpha-quality releases: useful for real testing, but APIs
|
|
9
|
+
may change before `1.0.0`.
|
|
10
|
+
- PEP 440 prerelease tags use the form `vX.Y.ZaN`, `vX.Y.ZbN`, or `vX.Y.ZrcN`.
|
|
11
|
+
Example: `v0.4.0a2`.
|
|
12
|
+
- Stable tags use the form `vX.Y.Z`. Example: `v0.4.0`.
|
|
13
|
+
- Never rewrite a pushed release tag. If a release is wrong, ship the next
|
|
14
|
+
version with a fix.
|
|
15
|
+
|
|
16
|
+
## What The Workflow Does
|
|
17
|
+
|
|
18
|
+
When a tag matching `v*.*.*` is pushed, GitHub Actions:
|
|
19
|
+
|
|
20
|
+
1. Verifies the tag matches `pyproject.toml` exactly after stripping the
|
|
21
|
+
leading `v`.
|
|
22
|
+
2. Builds the wheel and source distribution with `uv build`.
|
|
23
|
+
3. Publishes to PyPI through Trusted Publishing.
|
|
24
|
+
4. Creates a GitHub Release and attaches the built artifacts.
|
|
25
|
+
5. Marks tags containing PEP 440 alpha, beta, or release-candidate markers as
|
|
26
|
+
GitHub prereleases.
|
|
27
|
+
|
|
28
|
+
## Prerelease Versus Full Release
|
|
29
|
+
|
|
30
|
+
Use a prerelease while validating behavior with end-to-end tests:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
0.4.0a1
|
|
34
|
+
0.4.0a2
|
|
35
|
+
0.4.0rc1
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use a full release only when the same release line is ready for general use:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
0.4.0
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
PyPI treats `0.4.0a2` as a prerelease version. Users can install it explicitly:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uvx --from "gflow-cli==0.4.0a2" gflow --help
|
|
48
|
+
python -m pip install --pre gflow-cli
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Release Checklist
|
|
52
|
+
|
|
53
|
+
1. Confirm the working tree is clean:
|
|
54
|
+
```bash
|
|
55
|
+
git status --short
|
|
56
|
+
```
|
|
57
|
+
2. Confirm `main` is current:
|
|
58
|
+
```bash
|
|
59
|
+
git fetch origin
|
|
60
|
+
git branch --show-current
|
|
61
|
+
git rev-list HEAD..origin/main
|
|
62
|
+
```
|
|
63
|
+
3. Run quality gates:
|
|
64
|
+
```bash
|
|
65
|
+
uv run ruff check src tests
|
|
66
|
+
uv run ruff format --check src tests
|
|
67
|
+
uv run pyright src
|
|
68
|
+
uv run pytest -q
|
|
69
|
+
```
|
|
70
|
+
4. Update the version in:
|
|
71
|
+
- `pyproject.toml`
|
|
72
|
+
- `src/gflow_cli/__init__.py`
|
|
73
|
+
- any tests that assert the package version
|
|
74
|
+
5. Move user-visible changes from `CHANGELOG.md` `[Unreleased]` into a dated
|
|
75
|
+
release section.
|
|
76
|
+
6. Commit the release prep:
|
|
77
|
+
```bash
|
|
78
|
+
git add pyproject.toml src/gflow_cli/__init__.py CHANGELOG.md tests
|
|
79
|
+
git commit -m "chore(release): vX.Y.Z"
|
|
80
|
+
```
|
|
81
|
+
7. Tag and push:
|
|
82
|
+
```bash
|
|
83
|
+
git tag -a vX.Y.Z -m "vX.Y.Z"
|
|
84
|
+
git push origin main
|
|
85
|
+
git push origin vX.Y.Z
|
|
86
|
+
```
|
|
87
|
+
8. Watch the release workflow:
|
|
88
|
+
<https://github.com/ffroliva/gflow-cli/actions/workflows/release.yml>
|
|
89
|
+
9. Confirm the new version appears on:
|
|
90
|
+
- <https://pypi.org/project/gflow-cli/>
|
|
91
|
+
- <https://github.com/ffroliva/gflow-cli/releases>
|
|
92
|
+
|
|
93
|
+
## Known Historical Quirk
|
|
94
|
+
|
|
95
|
+
Older alpha tags (`v0.2.0a1`, `v0.3.0a1`) were created as normal GitHub
|
|
96
|
+
Releases because the workflow only detected hyphenated prerelease names. The
|
|
97
|
+
workflow now recognizes PEP 440 alpha, beta, and release-candidate tags.
|
|
@@ -230,7 +230,7 @@ Re-running `auth login` refreshes the cookies in place — no other state is los
|
|
|
230
230
|
|---|---|
|
|
231
231
|
| Session file leaked to a public repo | `.gitignore` excludes profile dirs at every layer. Recommended belt-and-braces: keep the gflow-cli home outside the repo (default location via `platformdirs` already does this) and run `git status` before any commit. Automatic in-repo detection is on the backlog (not yet scheduled). |
|
|
232
232
|
| Multi-user shared machine | Profiles live under each user's home dir; OS file permissions (`0700` on POSIX, ACL on Windows) prevent cross-user reads by default. |
|
|
233
|
-
| `gflow-cli` itself becomes malicious | The package is open-source under MIT; pin a version (`uv tool install gflow-cli==0.
|
|
233
|
+
| `gflow-cli` itself becomes malicious | The package is open-source under MIT; pin a version (`uv tool install gflow-cli==0.5.0a1`) and review release diffs before upgrading. |
|
|
234
234
|
| Stolen laptop | Anyone with disk access has your session. Use full-disk encryption (FileVault, BitLocker, LUKS). Consider a dedicated `--profile sandbox` for short-lived experiments. |
|
|
235
235
|
| Sharing a profile between machines | Technically works (copy the profile dir), but Google may flag the device-fingerprint mismatch as suspicious. Re-login on the new machine instead. |
|
|
236
236
|
|
|
@@ -7,6 +7,7 @@ Welcome to the `gflow-cli` documentation. This index is the routing layer: it te
|
|
|
7
7
|
| [README](../README.md) | Project overview, install, quick start | First time landing on the repo |
|
|
8
8
|
| [CLAUDE.md](../CLAUDE.md) | Project memory hub for AI coding agents | First time an agent (Claude/Cursor/Codex/Gemini/Aider) opens the repo |
|
|
9
9
|
| [PLAN.md](../PLAN.md) | Implementation plan (DDD / CQRS / phases / ADRs) | You want the architectural intent and roadmap |
|
|
10
|
+
| [RELEASE.md](../RELEASE.md) | Release checklist, prerelease policy, PyPI/GitHub publishing protocol | Cutting or auditing a release |
|
|
10
11
|
| [CHANGELOG](../CHANGELOG.md) | Version-by-version user-visible changes | Upgrading or auditing what shipped |
|
|
11
12
|
| [KNOWN_ISSUES](../KNOWN_ISSUES.md) | Open / mitigated / resolved issues with workarounds | Before opening a bug report; when something feels off |
|
|
12
13
|
| [DISCLAIMER](../DISCLAIMER.md) | Legal scope, takedown policy, prohibited uses | Before deploying anywhere non-trivial |
|
|
@@ -31,6 +32,7 @@ Welcome to the `gflow-cli` documentation. This index is the routing layer: it te
|
|
|
31
32
|
**"Exit code 4 (rate-limit) or 5 (content-policy) — how do I recover?"** → [USER_GUIDE § Journey 12](USER_GUIDE.md#journey-12--recovering-from-contentpolicyerror-or-ratelimiterror)
|
|
32
33
|
**"How do I read the structured log (`error_raised` events)?"** → [USER_GUIDE § Journey 6](USER_GUIDE.md#journey-6--reading-structured-logs-jq-recipes)
|
|
33
34
|
**"What exit code does shell branching see for each error class?"** → [USAGE § Exit codes](USAGE.md#exit-codes)
|
|
35
|
+
**"Is `v0.5.0a1` a prerelease, and how do I cut a full release?"** → [RELEASE § Prerelease Versus Full Release](../RELEASE.md#prerelease-versus-full-release)
|
|
34
36
|
**"Where is my session stored?"** → [AUTHENTICATION § Session storage](AUTHENTICATION.md#session-storage)
|
|
35
37
|
**"Where do generated files land?"** → [CONFIGURATION § Output paths](CONFIGURATION.md#output-paths)
|
|
36
38
|
**"How do I run with multiple Google accounts?"** → [AUTHENTICATION § Multiple accounts](AUTHENTICATION.md#multiple-accounts)
|
|
@@ -50,7 +50,7 @@ For users on shared / multi-user / production-adjacent machines:
|
|
|
50
50
|
- [ ] **Set `GFLOW_CLI_HOME` to a non-default path** if you want the session away from the standard `LOCALAPPDATA` / `~/.local/share` location for any reason (auditability, separate volumes).
|
|
51
51
|
- [ ] **Use `--profile sandbox`** for short-lived experiments. Easy to delete (`rm -rf $GFLOW_CLI_HOME/profile_sandbox`) without disturbing your main profile.
|
|
52
52
|
- [ ] **Rotate sessions monthly** by signing out of Google → re-running `gflow auth login`. Limits blast radius of an unnoticed session theft.
|
|
53
|
-
- [ ] **Pin a gflow-cli version** in production (`uv tool install gflow-cli==0.
|
|
53
|
+
- [ ] **Pin a gflow-cli version** in production (`uv tool install gflow-cli==0.5.0a1`) and review release diffs before upgrading.
|
|
54
54
|
- [ ] **Keep the package up-to-date for security fixes.** Subscribe to GitHub Releases for `ffroliva/gflow-cli`.
|
|
55
55
|
- [ ] **Scan your repo for accidentally-committed profiles** before pushing: `git ls-files | grep -E "profile_|cookies\.json|\.env$"`.
|
|
56
56
|
|