|
| 1 | +# Contributing |
| 2 | + |
| 3 | +Thanks for being here. This tool writes to live newsletters, so the bar is correctness |
| 4 | +first and features second. |
| 5 | + |
| 6 | +## Setup |
| 7 | + |
| 8 | +```bash |
| 9 | +git clone https://github.com/HighnessAtharva/substack-cli |
| 10 | +cd substack-cli |
| 11 | +pip install -e ".[dev]" |
| 12 | +pytest -q |
| 13 | +ruff check . |
| 14 | +``` |
| 15 | + |
| 16 | +The whole suite is offline and runs in under a second. It never touches the network and |
| 17 | +never needs credentials. |
| 18 | + |
| 19 | +## Before you open a pull request |
| 20 | + |
| 21 | +Run both: |
| 22 | + |
| 23 | +```bash |
| 24 | +pytest -q |
| 25 | +ruff check . |
| 26 | +``` |
| 27 | + |
| 28 | +Add a test for anything you change. Every existing test pins a bug that reached a live |
| 29 | +newsletter, and the comment above each one says which. Keep that pattern: the test name |
| 30 | +should describe the behavior, and a comment should say what went wrong without it. |
| 31 | + |
| 32 | +## Testing against a real publication |
| 33 | + |
| 34 | +Use a throwaway draft. Never test on a live post. |
| 35 | + |
| 36 | +```bash |
| 37 | +substack push examples/hello-world.md # creates a draft |
| 38 | +substack get <id> # inspect it |
| 39 | +substack delete <id> # clean up |
| 40 | +``` |
| 41 | + |
| 42 | +Do not run `publish`, `update`, or `unpublish` while testing. Those three change a public |
| 43 | +page and Substack has no undo. Their guard rails are covered by offline tests with a fake |
| 44 | +client in `tests/test_update.py`, which is the pattern to follow for anything else |
| 45 | +destructive. |
| 46 | + |
| 47 | +## Style |
| 48 | + |
| 49 | +The code is plain Python with no framework and no clever abstractions. Match what is |
| 50 | +already there. |
| 51 | + |
| 52 | +- Line length 100, enforced by ruff. |
| 53 | +- Names spelled out. `publication_id`, not `pid`. |
| 54 | +- A comment explains **why**, especially when the reason is an API quirk. Anything you |
| 55 | + learned the hard way belongs in a comment and in [docs/api-notes.md](docs/api-notes.md). |
| 56 | +- Errors are written for a person mid-task. Say what happened, then say what to do about |
| 57 | + it. Raise `CLIError`, never call `sys.exit` outside the entry point. |
| 58 | + |
| 59 | +## Good first contributions |
| 60 | + |
| 61 | +- More markdown coverage: nested lists, strikethrough, task lists. |
| 62 | +- Better table rendering: column alignment from the separator row, dark mode. |
| 63 | +- Comment and subscriber endpoints, which nothing here touches yet. |
| 64 | +- Shell completions for bash, zsh, and fish. |
| 65 | +- Anything in [docs/api-notes.md](docs/api-notes.md) you can verify, correct, or extend. |
| 66 | + |
| 67 | +## Reporting a bug |
| 68 | + |
| 69 | +Include the command you ran, the full output with `-v`, your Python version, and your OS. |
| 70 | + |
| 71 | +Never paste a session cookie into an issue. If you already did, sign out of all sessions |
| 72 | +from Substack's account settings, which invalidates it immediately. |
| 73 | + |
| 74 | +## Security |
| 75 | + |
| 76 | +Report anything sensitive privately. See [SECURITY.md](SECURITY.md). |
0 commit comments