fastws-cli 0.0.8__tar.gz → 0.0.9__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.
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/CHANGELOG.md +12 -0
- {fastws_cli-0.0.8/fastws_cli.egg-info → fastws_cli-0.0.9}/PKG-INFO +43 -4
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/README.md +41 -2
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/fastws/__init__.py +2 -1
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/fastws/core.py +269 -50
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/fastws/releases.py +19 -25
- {fastws_cli-0.0.8 → fastws_cli-0.0.9/fastws_cli.egg-info}/PKG-INFO +43 -4
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/fastws_cli.egg-info/SOURCES.txt +1 -0
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/fastws_cli.egg-info/entry_points.txt +1 -0
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/fastws_cli.egg-info/requires.txt +1 -1
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/pyproject.toml +2 -1
- fastws_cli-0.0.9/tests/test_build.py +54 -0
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/tests/test_releases.py +48 -13
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/tests/test_sync.py +188 -4
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/LICENSE +0 -0
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/MANIFEST.in +0 -0
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/fastws_cli.egg-info/dependency_links.txt +0 -0
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/fastws_cli.egg-info/top_level.txt +0 -0
- {fastws_cli-0.0.8 → fastws_cli-0.0.9}/setup.cfg +0 -0
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
<!-- do not remove -->
|
|
2
2
|
|
|
3
|
+
## 0.0.9
|
|
4
|
+
|
|
5
|
+
### New Features
|
|
6
|
+
|
|
7
|
+
- Add ws-build: build sdists of all workspace projects into a dists dir, skipping unchanged projects and pruning old versions ([#23](https://github.com/AnswerDotAI/fastws/issues/23))
|
|
8
|
+
- detect project from cwd, add --nodeps to skip the dependency closure, and map dir names to packages ([#22](https://github.com/AnswerDotAI/fastws/issues/22))
|
|
9
|
+
- Move `dep_key`, member graph, and closure helpers to ghapi (>=2.0.6) and use `dep_key`/`local_dep_graph`/`dep_closure` in core and releases ([#21](https://github.com/AnswerDotAI/fastws/issues/21))
|
|
10
|
+
- ws-sync: write content-hashed .git/fastws-cargo-key per crate, covering Cargo.lock and locally patched git deps, for uv cache-keys ([#20](https://github.com/AnswerDotAI/fastws/issues/20))
|
|
11
|
+
- Run cargo update before uv sync in `ws_sync` so Rust deps refresh first ([#19](https://github.com/AnswerDotAI/fastws/issues/19))
|
|
12
|
+
- Add out-of-tree repo support, auto-managed workspace excludes, and uv.sources preservation to ws-sync ([#18](https://github.com/AnswerDotAI/fastws/issues/18))
|
|
13
|
+
|
|
14
|
+
|
|
3
15
|
## 0.0.8
|
|
4
16
|
|
|
5
17
|
### New Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastws-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.9
|
|
4
4
|
Summary: Fast workspace tools for multi-repo management
|
|
5
5
|
Author: Jeremy Howard
|
|
6
6
|
License: Apache-2.0
|
|
@@ -12,7 +12,7 @@ Description-Content-Type: text/markdown
|
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
Requires-Dist: fastcore>=1.14.3
|
|
14
14
|
Requires-Dist: fastgit>=0.0.7
|
|
15
|
-
Requires-Dist: ghapi>=
|
|
15
|
+
Requires-Dist: ghapi>=2.0.6
|
|
16
16
|
Requires-Dist: packaging
|
|
17
17
|
Requires-Dist: tomli; python_version < "3.11"
|
|
18
18
|
Provides-Extra: dev
|
|
@@ -42,6 +42,17 @@ AnswerDotAI/fastship
|
|
|
42
42
|
AnswerDotAI/fastws
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
A line may add a checkout location after the repo, for repos that live outside
|
|
46
|
+
the workspace root (`~` ok). Every command then reads and writes them there, and
|
|
47
|
+
`ws-sync` editable-installs each Python project found inside (the repo root if it
|
|
48
|
+
has a `pyproject.toml`, else its immediate subdirectories), so one out-of-tree
|
|
49
|
+
repo can hold several small packages alongside non-Python content:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
AnswerDotAI/fastcore
|
|
53
|
+
jph00/private ~/private
|
|
54
|
+
```
|
|
55
|
+
|
|
45
56
|
## Commands
|
|
46
57
|
|
|
47
58
|
### `ws-clone`
|
|
@@ -80,6 +91,18 @@ ws-branches
|
|
|
80
91
|
ws-branches --expected develop
|
|
81
92
|
```
|
|
82
93
|
|
|
94
|
+
### `ws-build`
|
|
95
|
+
|
|
96
|
+
Build an sdist of each workspace project (including `repos.txt` checkouts outside the root) into a dists directory, `.dists` by default. A project is rebuilt only when a file in it is newer than its existing sdist, and older versions of a rebuilt package are pruned, so the directory always holds one current sdist per project. A failing project gets a warning without stopping the others, but the command then exits 1.
|
|
97
|
+
|
|
98
|
+
Progress goes to stderr; on success the dists path prints to stdout, so `$(ws-build)` in a script both refreshes the pool and yields its location. The result suits any resolver that takes a candidate pool, e.g. `uv pip install --find-links` or a docker build context for images that must test unreleased workspace packages:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
ws-build
|
|
102
|
+
ws-build --force # rebuild everything
|
|
103
|
+
ws-build --out /tmp/dists
|
|
104
|
+
```
|
|
105
|
+
|
|
83
106
|
### `ws-sync`
|
|
84
107
|
|
|
85
108
|
Sync the workspace metadata, pull local repos, and install updates.
|
|
@@ -88,11 +111,21 @@ It respects `tool.uv.workspace.members` and `exclude` when scanning local projec
|
|
|
88
111
|
member directory isn't a Python project yet (no `pyproject.toml`, e.g. a fresh empty clone), it
|
|
89
112
|
warns and skips the `uv sync` step instead of letting uv fail on the whole workspace.
|
|
90
113
|
|
|
114
|
+
The workspace `exclude` list is auto-managed: a top-level directory that isn't a valid Python
|
|
115
|
+
project and isn't a `repos.txt` checkout gets excluded automatically, and is un-excluded once it
|
|
116
|
+
gains a real `pyproject.toml`. Globs, entries for missing directories, and entries for `repos.txt`
|
|
117
|
+
checkouts are always kept, and `exclude = [...]` under `[tool.fastws]` in the workspace
|
|
118
|
+
`pyproject.toml` declares intent the scan can't infer (e.g. keeping a real project out of the
|
|
119
|
+
workspace). Hand-written `[tool.uv.sources]` entries (path, git, ...) are preserved when syncing
|
|
120
|
+
adds new members.
|
|
121
|
+
|
|
91
122
|
At most once per day (tracked by a stamp file inside the workspace's `.git`, so git never
|
|
92
123
|
sees it), the sync also floats dependencies: `uv sync -U` instead of plain `uv sync`, plus
|
|
93
124
|
a parallel `cargo update` in every member with a `Cargo.toml`, printing what moved. Pass
|
|
94
125
|
`--upgrade` to force that pass regardless of when it last ran.
|
|
95
126
|
|
|
127
|
+
Before every uv sync, `ws-sync` writes `.git/fastws-cargo-key` for each member crate. The key hashes `Cargo.lock` contents and the workspace Cargo patch configuration. For Git dependencies redirected to local paths by `[patch."<url>"]`, it also hashes each patched crate's `Cargo.toml`, `build.rs`, and `src` tree, recursively. The file is rewritten only when that content changes, so projects can use `{ file = ".git/fastws-cargo-key" }` in `tool.uv.cache-keys` without rebuilding after a timestamp-only `Cargo.lock` write.
|
|
128
|
+
|
|
96
129
|
```bash
|
|
97
130
|
ws-sync
|
|
98
131
|
ws-sync --workspace ~/aai-ws
|
|
@@ -104,12 +137,15 @@ ws-sync --upgrade
|
|
|
104
137
|
Add a repo to `repos.txt`, then run `ws-sync`. Given `owner/repo`, it clones; given the
|
|
105
138
|
name of an existing local folder (e.g. one just scaffolded with `nbdev-new` or `ship-new`),
|
|
106
139
|
it resolves `owner/repo` from the folder's `origin` remote instead, telling you exactly
|
|
107
|
-
what's missing if the folder has no git repo, no GitHub origin, or no `pyproject.toml
|
|
140
|
+
what's missing if the folder has no git repo, no GitHub origin, or no `pyproject.toml`.
|
|
141
|
+
Given a path outside the workspace root, the repo stays where it is and its location is
|
|
142
|
+
recorded in `repos.txt` (no root `pyproject.toml` needed: its packages are discovered on sync):
|
|
108
143
|
|
|
109
144
|
```bash
|
|
110
145
|
ws-add AnswerDotAI/fastws
|
|
111
146
|
ws-add answerdotai/fastws
|
|
112
147
|
ws-add fastws # existing local folder, resolved via its origin remote
|
|
148
|
+
ws-add ~/private # a path outside the workspace: stays where it is, recorded in repos.txt with its location
|
|
113
149
|
```
|
|
114
150
|
|
|
115
151
|
### `ws-remove`
|
|
@@ -129,11 +165,14 @@ ws-remove fastws # bare folder name also works if the directory exists
|
|
|
129
165
|
Report repos with commits since their newest GitHub release, so nothing reviewed sits unshipped:
|
|
130
166
|
|
|
131
167
|
```bash
|
|
132
|
-
ws-releases # sweep every repo in repos.txt
|
|
168
|
+
ws-releases # at the workspace root: sweep every repo in repos.txt
|
|
133
169
|
ws-releases solveit # only solveit's transitive workspace dependencies
|
|
170
|
+
ws-releases --nodeps # inside a repo: just that repo
|
|
134
171
|
ws-releases --skip 'wip' # extra start-of-message regex for commits that need no release
|
|
135
172
|
```
|
|
136
173
|
|
|
174
|
+
Run from inside a workspace checkout, the sweep narrows to that repo and its transitive workspace dependencies; `--nodeps` narrows it to the repo alone (an error when no project is in play).
|
|
175
|
+
|
|
137
176
|
Each pending repo lists its unreleased commit summaries; repos with no releases yet get one quiet `no releases:` line, and fully-released repos appear in `up to date:`. The newest release is picked by version number (publish timestamps can be out of order), and repos whose default branch isn't `main` are handled automatically.
|
|
138
177
|
|
|
139
178
|
Commits whose message matches a start-anchored regex from the skip set need no release and aren't reported. The built-in set covers version bumps and housekeeping (`bump`, `nbdev regen`, `.gitignore`, `docs`, `CI`, ...: `DEFAULT_SKIP` in `fastws.releases`); `[tool.fastws]` in the workspace root `pyproject.toml` adds to it, and names repos that should never be swept (apps that deploy rather than release):
|
|
@@ -19,6 +19,17 @@ AnswerDotAI/fastship
|
|
|
19
19
|
AnswerDotAI/fastws
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
A line may add a checkout location after the repo, for repos that live outside
|
|
23
|
+
the workspace root (`~` ok). Every command then reads and writes them there, and
|
|
24
|
+
`ws-sync` editable-installs each Python project found inside (the repo root if it
|
|
25
|
+
has a `pyproject.toml`, else its immediate subdirectories), so one out-of-tree
|
|
26
|
+
repo can hold several small packages alongside non-Python content:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
AnswerDotAI/fastcore
|
|
30
|
+
jph00/private ~/private
|
|
31
|
+
```
|
|
32
|
+
|
|
22
33
|
## Commands
|
|
23
34
|
|
|
24
35
|
### `ws-clone`
|
|
@@ -57,6 +68,18 @@ ws-branches
|
|
|
57
68
|
ws-branches --expected develop
|
|
58
69
|
```
|
|
59
70
|
|
|
71
|
+
### `ws-build`
|
|
72
|
+
|
|
73
|
+
Build an sdist of each workspace project (including `repos.txt` checkouts outside the root) into a dists directory, `.dists` by default. A project is rebuilt only when a file in it is newer than its existing sdist, and older versions of a rebuilt package are pruned, so the directory always holds one current sdist per project. A failing project gets a warning without stopping the others, but the command then exits 1.
|
|
74
|
+
|
|
75
|
+
Progress goes to stderr; on success the dists path prints to stdout, so `$(ws-build)` in a script both refreshes the pool and yields its location. The result suits any resolver that takes a candidate pool, e.g. `uv pip install --find-links` or a docker build context for images that must test unreleased workspace packages:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
ws-build
|
|
79
|
+
ws-build --force # rebuild everything
|
|
80
|
+
ws-build --out /tmp/dists
|
|
81
|
+
```
|
|
82
|
+
|
|
60
83
|
### `ws-sync`
|
|
61
84
|
|
|
62
85
|
Sync the workspace metadata, pull local repos, and install updates.
|
|
@@ -65,11 +88,21 @@ It respects `tool.uv.workspace.members` and `exclude` when scanning local projec
|
|
|
65
88
|
member directory isn't a Python project yet (no `pyproject.toml`, e.g. a fresh empty clone), it
|
|
66
89
|
warns and skips the `uv sync` step instead of letting uv fail on the whole workspace.
|
|
67
90
|
|
|
91
|
+
The workspace `exclude` list is auto-managed: a top-level directory that isn't a valid Python
|
|
92
|
+
project and isn't a `repos.txt` checkout gets excluded automatically, and is un-excluded once it
|
|
93
|
+
gains a real `pyproject.toml`. Globs, entries for missing directories, and entries for `repos.txt`
|
|
94
|
+
checkouts are always kept, and `exclude = [...]` under `[tool.fastws]` in the workspace
|
|
95
|
+
`pyproject.toml` declares intent the scan can't infer (e.g. keeping a real project out of the
|
|
96
|
+
workspace). Hand-written `[tool.uv.sources]` entries (path, git, ...) are preserved when syncing
|
|
97
|
+
adds new members.
|
|
98
|
+
|
|
68
99
|
At most once per day (tracked by a stamp file inside the workspace's `.git`, so git never
|
|
69
100
|
sees it), the sync also floats dependencies: `uv sync -U` instead of plain `uv sync`, plus
|
|
70
101
|
a parallel `cargo update` in every member with a `Cargo.toml`, printing what moved. Pass
|
|
71
102
|
`--upgrade` to force that pass regardless of when it last ran.
|
|
72
103
|
|
|
104
|
+
Before every uv sync, `ws-sync` writes `.git/fastws-cargo-key` for each member crate. The key hashes `Cargo.lock` contents and the workspace Cargo patch configuration. For Git dependencies redirected to local paths by `[patch."<url>"]`, it also hashes each patched crate's `Cargo.toml`, `build.rs`, and `src` tree, recursively. The file is rewritten only when that content changes, so projects can use `{ file = ".git/fastws-cargo-key" }` in `tool.uv.cache-keys` without rebuilding after a timestamp-only `Cargo.lock` write.
|
|
105
|
+
|
|
73
106
|
```bash
|
|
74
107
|
ws-sync
|
|
75
108
|
ws-sync --workspace ~/aai-ws
|
|
@@ -81,12 +114,15 @@ ws-sync --upgrade
|
|
|
81
114
|
Add a repo to `repos.txt`, then run `ws-sync`. Given `owner/repo`, it clones; given the
|
|
82
115
|
name of an existing local folder (e.g. one just scaffolded with `nbdev-new` or `ship-new`),
|
|
83
116
|
it resolves `owner/repo` from the folder's `origin` remote instead, telling you exactly
|
|
84
|
-
what's missing if the folder has no git repo, no GitHub origin, or no `pyproject.toml
|
|
117
|
+
what's missing if the folder has no git repo, no GitHub origin, or no `pyproject.toml`.
|
|
118
|
+
Given a path outside the workspace root, the repo stays where it is and its location is
|
|
119
|
+
recorded in `repos.txt` (no root `pyproject.toml` needed: its packages are discovered on sync):
|
|
85
120
|
|
|
86
121
|
```bash
|
|
87
122
|
ws-add AnswerDotAI/fastws
|
|
88
123
|
ws-add answerdotai/fastws
|
|
89
124
|
ws-add fastws # existing local folder, resolved via its origin remote
|
|
125
|
+
ws-add ~/private # a path outside the workspace: stays where it is, recorded in repos.txt with its location
|
|
90
126
|
```
|
|
91
127
|
|
|
92
128
|
### `ws-remove`
|
|
@@ -106,11 +142,14 @@ ws-remove fastws # bare folder name also works if the directory exists
|
|
|
106
142
|
Report repos with commits since their newest GitHub release, so nothing reviewed sits unshipped:
|
|
107
143
|
|
|
108
144
|
```bash
|
|
109
|
-
ws-releases # sweep every repo in repos.txt
|
|
145
|
+
ws-releases # at the workspace root: sweep every repo in repos.txt
|
|
110
146
|
ws-releases solveit # only solveit's transitive workspace dependencies
|
|
147
|
+
ws-releases --nodeps # inside a repo: just that repo
|
|
111
148
|
ws-releases --skip 'wip' # extra start-of-message regex for commits that need no release
|
|
112
149
|
```
|
|
113
150
|
|
|
151
|
+
Run from inside a workspace checkout, the sweep narrows to that repo and its transitive workspace dependencies; `--nodeps` narrows it to the repo alone (an error when no project is in play).
|
|
152
|
+
|
|
114
153
|
Each pending repo lists its unreleased commit summaries; repos with no releases yet get one quiet `no releases:` line, and fully-released repos appear in `up to date:`. The newest release is picked by version number (publish timestamps can be out of order), and repos whose default branch isn't `main` are handled automatically.
|
|
115
154
|
|
|
116
155
|
Commits whose message matches a start-anchored regex from the skip set need no release and aren't reported. The built-in set covers version bumps and housekeeping (`bump`, `nbdev regen`, `.gitignore`, `docs`, `CI`, ...: `DEFAULT_SKIP` in `fastws.releases`); `[tool.fastws]` in the workspace root `pyproject.toml` adds to it, and names repos that should never be swept (apps that deploy rather than release):
|