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.
@@ -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