springclean 0.1.0__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.
- springclean-0.1.0/LICENSE +21 -0
- springclean-0.1.0/PKG-INFO +390 -0
- springclean-0.1.0/README.md +358 -0
- springclean-0.1.0/pyproject.toml +72 -0
- springclean-0.1.0/setup.cfg +4 -0
- springclean-0.1.0/src/springclean/__init__.py +3 -0
- springclean-0.1.0/src/springclean/__main__.py +6 -0
- springclean-0.1.0/src/springclean/cli.py +92 -0
- springclean-0.1.0/src/springclean/env.py +38 -0
- springclean-0.1.0/src/springclean/errors.py +5 -0
- springclean-0.1.0/src/springclean/github.py +149 -0
- springclean-0.1.0/src/springclean/repo_refs.py +29 -0
- springclean-0.1.0/src/springclean/reports.py +470 -0
- springclean-0.1.0/src/springclean/tui.py +1175 -0
- springclean-0.1.0/src/springclean.egg-info/PKG-INFO +390 -0
- springclean-0.1.0/src/springclean.egg-info/SOURCES.txt +25 -0
- springclean-0.1.0/src/springclean.egg-info/dependency_links.txt +1 -0
- springclean-0.1.0/src/springclean.egg-info/entry_points.txt +2 -0
- springclean-0.1.0/src/springclean.egg-info/requires.txt +8 -0
- springclean-0.1.0/src/springclean.egg-info/top_level.txt +1 -0
- springclean-0.1.0/tests/test_cli.py +105 -0
- springclean-0.1.0/tests/test_env.py +43 -0
- springclean-0.1.0/tests/test_github.py +150 -0
- springclean-0.1.0/tests/test_repo_refs.py +20 -0
- springclean-0.1.0/tests/test_report_outputs.py +62 -0
- springclean-0.1.0/tests/test_reports.py +113 -0
- springclean-0.1.0/tests/test_tui.py +778 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mario Ribeiro
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: springclean
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Spring Clean is a read-only GitHub repository cleanup audit tool.
|
|
5
|
+
Author: Mario Ribeiro
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/marioribeiro/springclean
|
|
8
|
+
Project-URL: Repository, https://github.com/marioribeiro/springclean
|
|
9
|
+
Project-URL: Issues, https://github.com/marioribeiro/springclean/issues
|
|
10
|
+
Keywords: github,audit,branches,pull-requests,cleanup
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: textual>=8.2.5
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: build>=1.5.0; extra == "dev"
|
|
27
|
+
Requires-Dist: coverage[toml]>=7.13.5; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest>=9.0.3; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff>=0.15.12; extra == "dev"
|
|
30
|
+
Requires-Dist: twine>=6.2.0; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# Spring Clean
|
|
34
|
+
|
|
35
|
+
Spring Clean is a read-only GitHub repository cleanup tool. It helps teams review old branches and open pull requests so they can decide what to keep, close, or delete manually.
|
|
36
|
+
|
|
37
|
+
The command is called `springclean`.
|
|
38
|
+
|
|
39
|
+
Spring Clean never changes GitHub. It does not delete branches, close pull requests, push commits, or update repository settings.
|
|
40
|
+
|
|
41
|
+
## What It Does
|
|
42
|
+
|
|
43
|
+
- Shows saved audit reports in a terminal browser.
|
|
44
|
+
- Audits one GitHub repository at a time.
|
|
45
|
+
- Lists branches, latest activity, protection/default status, and associated pull requests.
|
|
46
|
+
- Lists currently open pull requests, including drafts.
|
|
47
|
+
- Adds cleanup status and reason columns to guide review.
|
|
48
|
+
- Adds editable `review_action` and `review_comment` columns for team decisions.
|
|
49
|
+
- Writes timestamped local files so reports do not overwrite each other.
|
|
50
|
+
- Can list repositories available to your GitHub token.
|
|
51
|
+
|
|
52
|
+
The terminal browser is built with [Textual](https://textual.textualize.io/), a Python framework for terminal user interfaces.
|
|
53
|
+
|
|
54
|
+
## What You Need
|
|
55
|
+
|
|
56
|
+
- Python 3.10 or newer.
|
|
57
|
+
- A GitHub token that can read the repositories you want to audit.
|
|
58
|
+
- Terminal access on the machine that can reach those repositories.
|
|
59
|
+
|
|
60
|
+
For private repositories, use a token with read access to repository contents and pull requests. A fine-grained GitHub token with read-only permissions is recommended.
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
Create and activate a virtual environment:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
python -m venv .venv
|
|
68
|
+
source .venv/bin/activate
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Install Spring Clean:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
python -m pip install springclean
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Create a local `.env` file in the directory where you will run Spring Clean:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
GITHUB_TOKEN=ghp_your_token_here
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Open Spring Clean:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
springclean
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
If your machine uses `python3` and `pip3`, use these instead:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
python3 -m venv .venv
|
|
93
|
+
source .venv/bin/activate
|
|
94
|
+
python3 -m pip install springclean
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Using The Browser
|
|
98
|
+
|
|
99
|
+
Run:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
springclean
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Spring Clean opens on the reports list. From there you can:
|
|
106
|
+
|
|
107
|
+
- load an existing report
|
|
108
|
+
- list repositories available to your token
|
|
109
|
+
- run a new audit
|
|
110
|
+
- search and filter rows
|
|
111
|
+
- tag branch and pull request rows for follow-up
|
|
112
|
+
- delete old local reports after confirmation
|
|
113
|
+
|
|
114
|
+
Keyboard controls:
|
|
115
|
+
|
|
116
|
+
| Key | Action |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| `o` | Show reports |
|
|
119
|
+
| `b` | Show branch report |
|
|
120
|
+
| `p` | Show pull request report |
|
|
121
|
+
| `g` | Enter a GitHub repo or URL and run a new audit |
|
|
122
|
+
| `l` | List repositories available to `GITHUB_TOKEN` |
|
|
123
|
+
| `d` | Delete the selected local report, or mark a branch for deletion / PR for closure |
|
|
124
|
+
| `k` | Mark the selected branch or PR as keep |
|
|
125
|
+
| `r` | Mark the selected branch or PR as review |
|
|
126
|
+
| `c` | Add or edit a short review comment |
|
|
127
|
+
| `u` | Clear the selected review action and comment |
|
|
128
|
+
| `enter` | Load the selected report or audit the selected GitHub repo |
|
|
129
|
+
| `/` | Focus search |
|
|
130
|
+
| `s` | Cycle filters |
|
|
131
|
+
| `a` | Reset to all rows |
|
|
132
|
+
| `escape` | Clear search or cancel a modal |
|
|
133
|
+
| `q` | Quit |
|
|
134
|
+
|
|
135
|
+
Delete only removes local Spring Clean report files. GitHub is not changed.
|
|
136
|
+
|
|
137
|
+
Review tags are saved back into the selected branch or pull request CSV. They do not call the GitHub API.
|
|
138
|
+
|
|
139
|
+
## Running Audits From The Command Line
|
|
140
|
+
|
|
141
|
+
The browser is the main workflow, but the CLI is useful for repeatable runs or scripts.
|
|
142
|
+
|
|
143
|
+
Audit branches:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
springclean repo marioribeiro/springclean --branch
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Audit open and draft pull requests:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
springclean repo marioribeiro/springclean --pr
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Audit both:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
springclean repo marioribeiro/springclean --branch --pr
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Use a different stale threshold:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
springclean repo marioribeiro/springclean --branch --pr --stale-days 180
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Choose another output directory:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
springclean repo marioribeiro/springclean --branch --pr --out team-reports
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Use another reports directory in the browser:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
springclean --reports-dir team-reports
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Show help:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
springclean --help
|
|
183
|
+
springclean repo --help
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Show the installed version:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
springclean --version
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Output Files
|
|
193
|
+
|
|
194
|
+
By default, reports are written to `./reports`.
|
|
195
|
+
|
|
196
|
+
File names include the repository and UTC timestamp:
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
reports/marioribeiro_springclean_20260507T134500Z_branches.csv
|
|
200
|
+
reports/marioribeiro_springclean_20260507T134500Z_pull_requests.csv
|
|
201
|
+
reports/marioribeiro_springclean_20260507T134500Z_summary.md
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Generated reports may contain private repo names, branch names, pull request titles, and usernames. Treat them as internal artifacts when auditing private repositories.
|
|
205
|
+
|
|
206
|
+
## Branch Report
|
|
207
|
+
|
|
208
|
+
The branch CSV includes:
|
|
209
|
+
|
|
210
|
+
- branch name and GitHub links
|
|
211
|
+
- best-effort branch creator/context owner
|
|
212
|
+
- default and protected flags
|
|
213
|
+
- latest commit metadata
|
|
214
|
+
- days since latest commit
|
|
215
|
+
- GitHub-like activity bucket
|
|
216
|
+
- associated pull request numbers, authors, states, and URLs
|
|
217
|
+
- cleanup status and reason
|
|
218
|
+
- editable `review_action` and `review_comment` columns
|
|
219
|
+
|
|
220
|
+
GitHub does not expose a durable branch creator field through the branch API. `branch_created_by` is inferred in this order:
|
|
221
|
+
|
|
222
|
+
1. Associated PR author, when GitHub links the branch to a PR
|
|
223
|
+
2. Latest commit author
|
|
224
|
+
3. Latest commit committer
|
|
225
|
+
|
|
226
|
+
`branch_created_by_source` records which fallback was used.
|
|
227
|
+
|
|
228
|
+
Branch buckets:
|
|
229
|
+
|
|
230
|
+
| Bucket | Meaning |
|
|
231
|
+
| --- | --- |
|
|
232
|
+
| `default` | Repository default branch |
|
|
233
|
+
| `active` | Non-default branch with commits inside the stale threshold |
|
|
234
|
+
| `stale` | Non-default branch with no commits inside the stale threshold |
|
|
235
|
+
|
|
236
|
+
Branch cleanup statuses:
|
|
237
|
+
|
|
238
|
+
| Status | Meaning |
|
|
239
|
+
| --- | --- |
|
|
240
|
+
| `keep_default` | Default branch |
|
|
241
|
+
| `keep_protected` | Protected branch |
|
|
242
|
+
| `review_active` | Branch has recent commit activity |
|
|
243
|
+
| `review_stale_open_pr` | Stale branch has at least one associated open PR |
|
|
244
|
+
| `candidate_stale_merged_pr` | Stale branch has at least one associated merged PR |
|
|
245
|
+
| `candidate_stale_closed_pr` | Stale branch only has closed/unmerged associated PRs |
|
|
246
|
+
| `candidate_stale_no_pr` | Stale branch has no associated PRs |
|
|
247
|
+
|
|
248
|
+
## Pull Request Report
|
|
249
|
+
|
|
250
|
+
The pull request CSV includes only currently open pull requests, including drafts.
|
|
251
|
+
|
|
252
|
+
It includes:
|
|
253
|
+
|
|
254
|
+
- PR number, title, state, and draft flag
|
|
255
|
+
- `created_by`
|
|
256
|
+
- base and head branch details
|
|
257
|
+
- created and updated timestamps
|
|
258
|
+
- age columns
|
|
259
|
+
- GitHub URL
|
|
260
|
+
- cleanup status and reason
|
|
261
|
+
- editable `review_action` and `review_comment` columns
|
|
262
|
+
|
|
263
|
+
Pull request cleanup statuses:
|
|
264
|
+
|
|
265
|
+
| Status | Meaning |
|
|
266
|
+
| --- | --- |
|
|
267
|
+
| `open_active` | Open PR updated inside the stale threshold |
|
|
268
|
+
| `open_stale` | Open PR not updated inside the stale threshold |
|
|
269
|
+
| `draft_active` | Draft PR updated inside the stale threshold |
|
|
270
|
+
| `draft_stale` | Draft PR not updated inside the stale threshold |
|
|
271
|
+
|
|
272
|
+
## Summary
|
|
273
|
+
|
|
274
|
+
The Markdown summary includes:
|
|
275
|
+
|
|
276
|
+
- repo name and default branch
|
|
277
|
+
- generation timestamp
|
|
278
|
+
- stale threshold
|
|
279
|
+
- branch counts by bucket and cleanup status
|
|
280
|
+
- open PR counts by draft/ready state and cleanup status
|
|
281
|
+
|
|
282
|
+
Use it as a quick overview before reviewing rows in the browser or CSV.
|
|
283
|
+
|
|
284
|
+
## Troubleshooting
|
|
285
|
+
|
|
286
|
+
`Missing GITHUB_TOKEN`
|
|
287
|
+
|
|
288
|
+
Add `GITHUB_TOKEN` to `.env`, or set it in the shell where you run Spring Clean.
|
|
289
|
+
|
|
290
|
+
`Could not access owner/repo`
|
|
291
|
+
|
|
292
|
+
Check that the repository name is in `owner/name` format, the token can access that repository, and the command is running from the directory that contains your `.env`.
|
|
293
|
+
|
|
294
|
+
`GitHub API returned 403`
|
|
295
|
+
|
|
296
|
+
The token may not have enough permission, the API rate limit may be exhausted, or GitHub may have applied a secondary rate limit. Wait and retry, or use a token with the expected repository access.
|
|
297
|
+
|
|
298
|
+
`python: command not found`
|
|
299
|
+
|
|
300
|
+
Try the same command with `python3`:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
python3 -m pip install springclean
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## For Developers
|
|
307
|
+
|
|
308
|
+
Install development dependencies:
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
python -m pip install -e ".[dev]"
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Create a local `.env` file from the example when working from the repository:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
cp .env.example .env
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Run tests:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
coverage run -m pytest
|
|
324
|
+
coverage report
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
The coverage gate is configured at 95%.
|
|
328
|
+
|
|
329
|
+
Run lint and formatting checks:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
ruff check .
|
|
333
|
+
ruff format --check .
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Build and check the package:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
python -m build
|
|
340
|
+
python -m twine check dist/*
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Useful local checks:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
springclean --help
|
|
347
|
+
springclean repo --help
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Publishing
|
|
351
|
+
|
|
352
|
+
The PyPI package name is `springclean`.
|
|
353
|
+
|
|
354
|
+
Publishing uses PyPI Trusted Publishing through GitHub Actions. Before the first release, create pending trusted publishers in PyPI and TestPyPI with these values:
|
|
355
|
+
|
|
356
|
+
| Field | PyPI | TestPyPI |
|
|
357
|
+
| --- | --- | --- |
|
|
358
|
+
| PyPI project name | `springclean` | `springclean` |
|
|
359
|
+
| Owner | `marioribeiro` | `marioribeiro` |
|
|
360
|
+
| Repository | `springclean` | `springclean` |
|
|
361
|
+
| Workflow | `publish.yml` | `publish.yml` |
|
|
362
|
+
| Environment | `pypi` | `testpypi` |
|
|
363
|
+
|
|
364
|
+
Require manual approval for the `pypi` GitHub environment before publishing real releases.
|
|
365
|
+
|
|
366
|
+
To test the package flow without publishing to PyPI, run the `Publish` workflow manually. That publishes to TestPyPI.
|
|
367
|
+
|
|
368
|
+
To publish a real release:
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
git tag v0.1.0
|
|
372
|
+
git push origin v0.1.0
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Main runtime dependency:
|
|
376
|
+
|
|
377
|
+
- [Textual](https://textual.textualize.io/) for the terminal browser
|
|
378
|
+
|
|
379
|
+
## Project Principles
|
|
380
|
+
|
|
381
|
+
- Product name in prose: **Spring Clean**
|
|
382
|
+
- CLI command: `springclean`
|
|
383
|
+
- Read-only by default and by design
|
|
384
|
+
- CSV-first for easy team review
|
|
385
|
+
- Terminal review should work from saved report files unless the user explicitly asks for a GitHub action
|
|
386
|
+
- Prefer explicit cleanup signals over hidden automation
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
MIT
|