fastws-cli 0.0.7__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.9/CHANGELOG.md +59 -0
- fastws_cli-0.0.9/PKG-INFO +193 -0
- fastws_cli-0.0.9/README.md +170 -0
- fastws_cli-0.0.9/fastws/__init__.py +8 -0
- fastws_cli-0.0.9/fastws/core.py +677 -0
- fastws_cli-0.0.9/fastws/releases.py +102 -0
- fastws_cli-0.0.9/fastws_cli.egg-info/PKG-INFO +193 -0
- {fastws_cli-0.0.7 → fastws_cli-0.0.9}/fastws_cli.egg-info/SOURCES.txt +3 -0
- fastws_cli-0.0.9/fastws_cli.egg-info/entry_points.txt +10 -0
- {fastws_cli-0.0.7 → fastws_cli-0.0.9}/fastws_cli.egg-info/requires.txt +4 -2
- {fastws_cli-0.0.7 → fastws_cli-0.0.9}/pyproject.toml +13 -8
- fastws_cli-0.0.9/tests/test_build.py +54 -0
- fastws_cli-0.0.9/tests/test_releases.py +95 -0
- fastws_cli-0.0.9/tests/test_sync.py +684 -0
- fastws_cli-0.0.7/CHANGELOG.md +0 -31
- fastws_cli-0.0.7/PKG-INFO +0 -99
- fastws_cli-0.0.7/README.md +0 -78
- fastws_cli-0.0.7/fastws/__init__.py +0 -5
- fastws_cli-0.0.7/fastws/core.py +0 -376
- fastws_cli-0.0.7/fastws_cli.egg-info/PKG-INFO +0 -99
- fastws_cli-0.0.7/fastws_cli.egg-info/entry_points.txt +0 -7
- fastws_cli-0.0.7/tests/test_sync.py +0 -236
- {fastws_cli-0.0.7 → fastws_cli-0.0.9}/LICENSE +0 -0
- {fastws_cli-0.0.7 → fastws_cli-0.0.9}/MANIFEST.in +0 -0
- {fastws_cli-0.0.7 → fastws_cli-0.0.9}/fastws_cli.egg-info/dependency_links.txt +0 -0
- {fastws_cli-0.0.7 → fastws_cli-0.0.9}/fastws_cli.egg-info/top_level.txt +0 -0
- {fastws_cli-0.0.7 → fastws_cli-0.0.9}/setup.cfg +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!-- do not remove -->
|
|
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
|
+
|
|
15
|
+
## 0.0.8
|
|
16
|
+
|
|
17
|
+
### New Features
|
|
18
|
+
|
|
19
|
+
- Add ws-releases: report unreleased commits across the workspace, with configurable skip patterns and repo exclusions ([#17](https://github.com/AnswerDotAI/fastws/pull/17)), thanks to [@jph00](https://github.com/jph00)
|
|
20
|
+
- Add once-daily dependency floating to ws_sync (uv sync -U + cargo update), with --upgrade flag to force ([#15](https://github.com/AnswerDotAI/fastws/issues/15))
|
|
21
|
+
- ws-sync skips uv sync for member dirs lacking pyproject.toml; ws-add resolves local folder names via origin remote ([#12](https://github.com/AnswerDotAI/fastws/issues/12))
|
|
22
|
+
- Allow bare folder name in ws-remove; separate directory deletion confirmation from metadata removal ([#9](https://github.com/AnswerDotAI/fastws/issues/9))
|
|
23
|
+
- Add `ws-remove` command to delete a repo from the workspace; refactor CLI wrappers with `@delegates` ([#8](https://github.com/AnswerDotAI/fastws/issues/8))
|
|
24
|
+
- Add [dev] extra to workspace dependencies and filter spurious warnings ([#7](https://github.com/AnswerDotAI/fastws/pull/7)), thanks to [@RensDimmendaal](https://github.com/RensDimmendaal)
|
|
25
|
+
- add --workers flag to ws-sync ([#6](https://github.com/AnswerDotAI/fastws/pull/6)), thanks to [@RensDimmendaal](https://github.com/RensDimmendaal)
|
|
26
|
+
|
|
27
|
+
### Bugs Squashed
|
|
28
|
+
|
|
29
|
+
- Preserving existing tool.uv.sources entries during ws-sync ([#14](https://github.com/AnswerDotAI/fastws/pull/14)), thanks to [@kafkasl](https://github.com/kafkasl)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## 0.0.7
|
|
33
|
+
|
|
34
|
+
### New Features
|
|
35
|
+
|
|
36
|
+
- Refactor Pyright editable path setup to write pyrightconfig.json instead of .pth files ([#4](https://github.com/AnswerDotAI/fastws/issues/4))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## 0.0.6
|
|
40
|
+
|
|
41
|
+
### New Features
|
|
42
|
+
|
|
43
|
+
- Add root-aware clone/pull helpers, auto-pull in ws-sync, and docstrings to CLI entry points ([#2](https://github.com/AnswerDotAI/fastws/issues/2))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## 0.0.5
|
|
47
|
+
|
|
48
|
+
### New Features
|
|
49
|
+
|
|
50
|
+
- Add ws-sync and ws-add commands with workspace metadata sync and Pyright editable path support ([#1](https://github.com/AnswerDotAI/fastws/issues/1))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
## 0.0.3
|
|
54
|
+
|
|
55
|
+
- change names
|
|
56
|
+
|
|
57
|
+
## 0.0.2
|
|
58
|
+
|
|
59
|
+
- init release
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastws-cli
|
|
3
|
+
Version: 0.0.9
|
|
4
|
+
Summary: Fast workspace tools for multi-repo management
|
|
5
|
+
Author: Jeremy Howard
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/AnswerDotAI/fastws
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: fastcore>=1.14.3
|
|
14
|
+
Requires-Dist: fastgit>=0.0.7
|
|
15
|
+
Requires-Dist: ghapi>=2.0.6
|
|
16
|
+
Requires-Dist: packaging
|
|
17
|
+
Requires-Dist: tomli; python_version < "3.11"
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: fastship; extra == "dev"
|
|
20
|
+
Requires-Dist: build; extra == "dev"
|
|
21
|
+
Requires-Dist: twine; extra == "dev"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# fastws
|
|
25
|
+
|
|
26
|
+
Fast workspace tools for multi-repo management.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install fastws-cli
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Setup
|
|
35
|
+
|
|
36
|
+
Create a `repos.txt` file listing your repos (one per line):
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
AnswerDotAI/fastcore
|
|
40
|
+
AnswerDotAI/fastgit
|
|
41
|
+
AnswerDotAI/fastship
|
|
42
|
+
AnswerDotAI/fastws
|
|
43
|
+
```
|
|
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
|
+
|
|
56
|
+
## Commands
|
|
57
|
+
|
|
58
|
+
### `ws-clone`
|
|
59
|
+
|
|
60
|
+
Clone all repos from your repos file:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
ws-clone
|
|
64
|
+
ws-clone --repos-file myrepos.txt
|
|
65
|
+
ws-clone --workers 8
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `ws-pull`
|
|
69
|
+
|
|
70
|
+
Pull updates for all repos (parallel):
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
ws-pull
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### `ws-status`
|
|
77
|
+
|
|
78
|
+
Show uncommitted changes and unpushed commits:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
ws-status
|
|
82
|
+
ws-status --branches
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `ws-branches`
|
|
86
|
+
|
|
87
|
+
Check if all repos are on the expected branch:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
ws-branches
|
|
91
|
+
ws-branches --expected develop
|
|
92
|
+
```
|
|
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
|
+
|
|
106
|
+
### `ws-sync`
|
|
107
|
+
|
|
108
|
+
Sync the workspace metadata, pull local repos, and install updates.
|
|
109
|
+
By default it uses the active venv parent as the workspace root, so you do not need to `cd` first.
|
|
110
|
+
It respects `tool.uv.workspace.members` and `exclude` when scanning local projects, and if any
|
|
111
|
+
member directory isn't a Python project yet (no `pyproject.toml`, e.g. a fresh empty clone), it
|
|
112
|
+
warns and skips the `uv sync` step instead of letting uv fail on the whole workspace.
|
|
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
|
+
|
|
122
|
+
At most once per day (tracked by a stamp file inside the workspace's `.git`, so git never
|
|
123
|
+
sees it), the sync also floats dependencies: `uv sync -U` instead of plain `uv sync`, plus
|
|
124
|
+
a parallel `cargo update` in every member with a `Cargo.toml`, printing what moved. Pass
|
|
125
|
+
`--upgrade` to force that pass regardless of when it last ran.
|
|
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
|
+
|
|
129
|
+
```bash
|
|
130
|
+
ws-sync
|
|
131
|
+
ws-sync --workspace ~/aai-ws
|
|
132
|
+
ws-sync --upgrade
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### `ws-add`
|
|
136
|
+
|
|
137
|
+
Add a repo to `repos.txt`, then run `ws-sync`. Given `owner/repo`, it clones; given the
|
|
138
|
+
name of an existing local folder (e.g. one just scaffolded with `nbdev-new` or `ship-new`),
|
|
139
|
+
it resolves `owner/repo` from the folder's `origin` remote instead, telling you exactly
|
|
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):
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
ws-add AnswerDotAI/fastws
|
|
146
|
+
ws-add answerdotai/fastws
|
|
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
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `ws-remove`
|
|
152
|
+
|
|
153
|
+
Remove a repo: delete its clone, and drop it from `repos.txt` and the workspace
|
|
154
|
+
`pyproject.toml`, then run `uv sync`. It refuses if the directory has uncommitted
|
|
155
|
+
changes, unpushed commits, no `origin` remote, or isn't a clean git checkout, and
|
|
156
|
+
always prompts for confirmation before deleting anything:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
ws-remove AnswerDotAI/fastws
|
|
160
|
+
ws-remove fastws # bare folder name also works if the directory exists
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### `ws-releases`
|
|
164
|
+
|
|
165
|
+
Report repos with commits since their newest GitHub release, so nothing reviewed sits unshipped:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
ws-releases # at the workspace root: sweep every repo in repos.txt
|
|
169
|
+
ws-releases solveit # only solveit's transitive workspace dependencies
|
|
170
|
+
ws-releases --nodeps # inside a repo: just that repo
|
|
171
|
+
ws-releases --skip 'wip' # extra start-of-message regex for commits that need no release
|
|
172
|
+
```
|
|
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
|
+
|
|
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.
|
|
177
|
+
|
|
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):
|
|
179
|
+
|
|
180
|
+
```toml
|
|
181
|
+
[tool.fastws]
|
|
182
|
+
release_skip = ["docs only"]
|
|
183
|
+
release_exclude = ["solveit", "md_site"]
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
From Python (the primary interface - the CLI is a thin wrapper over `fastws.releases`):
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from fastws import check_releases, check_release
|
|
190
|
+
await check_releases() # ReleaseReport: the repr is the report
|
|
191
|
+
await check_releases('solveit') # dependency-closure mode
|
|
192
|
+
await check_release('mdhtml') # one repo: list of unreleased commit summaries (None = no releases)
|
|
193
|
+
```
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# fastws
|
|
2
|
+
|
|
3
|
+
Fast workspace tools for multi-repo management.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install fastws-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Create a `repos.txt` file listing your repos (one per line):
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
AnswerDotAI/fastcore
|
|
17
|
+
AnswerDotAI/fastgit
|
|
18
|
+
AnswerDotAI/fastship
|
|
19
|
+
AnswerDotAI/fastws
|
|
20
|
+
```
|
|
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
|
+
|
|
33
|
+
## Commands
|
|
34
|
+
|
|
35
|
+
### `ws-clone`
|
|
36
|
+
|
|
37
|
+
Clone all repos from your repos file:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
ws-clone
|
|
41
|
+
ws-clone --repos-file myrepos.txt
|
|
42
|
+
ws-clone --workers 8
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### `ws-pull`
|
|
46
|
+
|
|
47
|
+
Pull updates for all repos (parallel):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
ws-pull
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### `ws-status`
|
|
54
|
+
|
|
55
|
+
Show uncommitted changes and unpushed commits:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
ws-status
|
|
59
|
+
ws-status --branches
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### `ws-branches`
|
|
63
|
+
|
|
64
|
+
Check if all repos are on the expected branch:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
ws-branches
|
|
68
|
+
ws-branches --expected develop
|
|
69
|
+
```
|
|
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
|
+
|
|
83
|
+
### `ws-sync`
|
|
84
|
+
|
|
85
|
+
Sync the workspace metadata, pull local repos, and install updates.
|
|
86
|
+
By default it uses the active venv parent as the workspace root, so you do not need to `cd` first.
|
|
87
|
+
It respects `tool.uv.workspace.members` and `exclude` when scanning local projects, and if any
|
|
88
|
+
member directory isn't a Python project yet (no `pyproject.toml`, e.g. a fresh empty clone), it
|
|
89
|
+
warns and skips the `uv sync` step instead of letting uv fail on the whole workspace.
|
|
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
|
+
|
|
99
|
+
At most once per day (tracked by a stamp file inside the workspace's `.git`, so git never
|
|
100
|
+
sees it), the sync also floats dependencies: `uv sync -U` instead of plain `uv sync`, plus
|
|
101
|
+
a parallel `cargo update` in every member with a `Cargo.toml`, printing what moved. Pass
|
|
102
|
+
`--upgrade` to force that pass regardless of when it last ran.
|
|
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
|
+
|
|
106
|
+
```bash
|
|
107
|
+
ws-sync
|
|
108
|
+
ws-sync --workspace ~/aai-ws
|
|
109
|
+
ws-sync --upgrade
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `ws-add`
|
|
113
|
+
|
|
114
|
+
Add a repo to `repos.txt`, then run `ws-sync`. Given `owner/repo`, it clones; given the
|
|
115
|
+
name of an existing local folder (e.g. one just scaffolded with `nbdev-new` or `ship-new`),
|
|
116
|
+
it resolves `owner/repo` from the folder's `origin` remote instead, telling you exactly
|
|
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):
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
ws-add AnswerDotAI/fastws
|
|
123
|
+
ws-add answerdotai/fastws
|
|
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
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `ws-remove`
|
|
129
|
+
|
|
130
|
+
Remove a repo: delete its clone, and drop it from `repos.txt` and the workspace
|
|
131
|
+
`pyproject.toml`, then run `uv sync`. It refuses if the directory has uncommitted
|
|
132
|
+
changes, unpushed commits, no `origin` remote, or isn't a clean git checkout, and
|
|
133
|
+
always prompts for confirmation before deleting anything:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
ws-remove AnswerDotAI/fastws
|
|
137
|
+
ws-remove fastws # bare folder name also works if the directory exists
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `ws-releases`
|
|
141
|
+
|
|
142
|
+
Report repos with commits since their newest GitHub release, so nothing reviewed sits unshipped:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
ws-releases # at the workspace root: sweep every repo in repos.txt
|
|
146
|
+
ws-releases solveit # only solveit's transitive workspace dependencies
|
|
147
|
+
ws-releases --nodeps # inside a repo: just that repo
|
|
148
|
+
ws-releases --skip 'wip' # extra start-of-message regex for commits that need no release
|
|
149
|
+
```
|
|
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
|
+
|
|
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.
|
|
154
|
+
|
|
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):
|
|
156
|
+
|
|
157
|
+
```toml
|
|
158
|
+
[tool.fastws]
|
|
159
|
+
release_skip = ["docs only"]
|
|
160
|
+
release_exclude = ["solveit", "md_site"]
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
From Python (the primary interface - the CLI is a thin wrapper over `fastws.releases`):
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from fastws import check_releases, check_release
|
|
167
|
+
await check_releases() # ReleaseReport: the repr is the report
|
|
168
|
+
await check_releases('solveit') # dependency-closure mode
|
|
169
|
+
await check_release('mdhtml') # one repo: list of unreleased commit summaries (None = no releases)
|
|
170
|
+
```
|