@alien-protocol/cannon 2.2.2

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.
package/.env.example ADDED
@@ -0,0 +1,12 @@
1
+ # ─────────────────────────────────────────────
2
+ # .env.example — copy to .env (never commit .env!)
3
+ # ─────────────────────────────────────────────
4
+
5
+ # Your GitHub Personal Access Token
6
+ # Create one at: https://github.com/settings/tokens/new
7
+ # Required scope: repo (or public_repo for public repos only)
8
+ GITHUB_TOKEN=ghp_your_token_here
9
+
10
+ # Database connection strings (only needed for DB sources)
11
+ POSTGRES_URL=postgres://user:password@localhost:5432/mydb
12
+ MYSQL_URL=mysql://user:password@localhost:3306/mydb
package/README.md ADDED
@@ -0,0 +1,395 @@
1
+ # 🛸 @alien-protocol/cannon
2
+
3
+ > Bulk-create GitHub issues from **CSV, PDF, DOCX, JSON, or any SQL database** — one config file, safe delays, duplicate detection, and resume support.
4
+
5
+ ## Installation
6
+
7
+ **Option A — Install globally (recommended)**
8
+ Run once, then use `cannon` anywhere:
9
+
10
+ ```bash
11
+ npm install -g @alien-protocol/cannon
12
+ ```
13
+
14
+ **Option B — No install, use npx**
15
+ Prefix every command with `npx @alien-protocol/cannon`:
16
+
17
+ ```bash
18
+ npx @alien-protocol/cannon init
19
+ npx @alien-protocol/cannon fire --preview
20
+ ```
21
+
22
+ > All examples in this README use the global `cannon` command.
23
+ > If you chose Option B, just add `npx @alien-protocol/cannon` in front of each one.
24
+
25
+ ---
26
+
27
+ ## Quick Start
28
+
29
+ ```bash
30
+ # 1. Create your config file
31
+ cannon init
32
+
33
+ # 2. Login with GitHub (no token needed)
34
+ cannon auth login
35
+
36
+ # 3. Preview — nothing gets created
37
+ cannon fire --preview
38
+
39
+ # 4. Create your issues
40
+ cannon fire
41
+ ```
42
+
43
+ ---
44
+
45
+ ## The Config File
46
+
47
+ `cannon init` creates this in your project. Edit it, then run `cannon fire`.
48
+
49
+ ```json
50
+ {
51
+ "source": {
52
+ "//": "type options: csv | json | pdf | docx | sqlite | postgres | mysql",
53
+ "type": "csv",
54
+ "file": "./issues.csv"
55
+ },
56
+
57
+ "mode": {
58
+ "//": "safeMode adds random delays — always keep true for large batches",
59
+ "safeMode": true,
60
+ "dryRun": false,
61
+ "resumable": true
62
+ },
63
+
64
+ "delay": {
65
+ "//": "minutes between each issue — only used when safeMode is true",
66
+ "min": 4,
67
+ "max": 8
68
+ },
69
+
70
+ "labels": {
71
+ "//": "autoCreate will create missing labels in GitHub automatically",
72
+ "autoCreate": false,
73
+ "colors": {
74
+ "bug": "ee0701",
75
+ "enhancement": "0075ca",
76
+ "documentation": "0052cc",
77
+ "security": "e11d48",
78
+ "performance": "f97316",
79
+ "accessibility": "8b5cf6"
80
+ }
81
+ },
82
+
83
+ "output": {
84
+ "//": "logFile path to save a JSON log after each run — leave blank to skip",
85
+ "logFile": "",
86
+ "showTable": true
87
+ },
88
+
89
+ "notify": {
90
+ "//": "webhookUrl accepts any Slack / Discord / Teams incoming webhook URL",
91
+ "webhookUrl": "",
92
+ "onSuccess": true,
93
+ "onFailure": true
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### Config Options
99
+
100
+ | Key | Default | Description |
101
+ | ------------------------- | -------------- | ----------------------------------------------------------------- |
102
+ | `source.type` | `csv` | `csv` · `json` · `pdf` · `docx` · `sqlite` · `postgres` · `mysql` |
103
+ | `source.file` | `./issues.csv` | Path to your issues file |
104
+ | `source.query` | — | SQL query (database sources only) |
105
+ | `source.connectionString` | — | DB connection URL — use `${ENV_VAR}`, never hardcode |
106
+ | `mode.safeMode` | `true` | Random delays between issues — keeps you off GitHub's radar |
107
+ | `mode.dryRun` | `false` | Preview only, nothing created |
108
+ | `mode.resumable` | `true` | Saves progress so you can stop and restart safely |
109
+ | `delay.min` | `4` | Minimum minutes between issues |
110
+ | `delay.max` | `8` | Maximum minutes between issues |
111
+ | `labels.autoCreate` | `false` | Auto-create missing labels in GitHub |
112
+ | `labels.colors` | see above | Label name → hex color for auto-creation |
113
+ | `output.logFile` | — | Save a JSON results log to this path |
114
+ | `output.showTable` | `true` | Show a summary table after completion |
115
+ | `notify.webhookUrl` | — | Slack / Discord / Teams webhook URL |
116
+ | `notify.onSuccess` | `true` | Notify when batch completes successfully |
117
+ | `notify.onFailure` | `true` | Notify when any issues fail |
118
+
119
+ ---
120
+
121
+ ## Commands
122
+
123
+ ### `cannon init`
124
+
125
+ Creates `cannon.config.json` with defaults. Edit it, then fire.
126
+
127
+ ```bash
128
+ cannon init # create config
129
+ cannon init --force # overwrite existing config
130
+ ```
131
+
132
+ ---
133
+
134
+ ### `cannon auth`
135
+
136
+ Secure GitHub login — no token copying needed.
137
+
138
+ ```bash
139
+ cannon auth login # login via GitHub OAuth
140
+ cannon auth status # show who you're logged in as
141
+ cannon auth logout # remove saved credentials
142
+ ```
143
+
144
+ How it works: cannon shows you a short code → you enter it at `github.com/login/device` → done. Token is saved to `~/.cannon/credentials.json`, never in your project.
145
+
146
+ ---
147
+
148
+ ### `cannon validate`
149
+
150
+ Checks everything before you fire — catches problems early.
151
+
152
+ ```bash
153
+ cannon validate
154
+ ```
155
+
156
+ Checks your config is valid JSON · token is present · source file exists · issues can be loaded.
157
+
158
+ ---
159
+
160
+ ### `cannon fire`
161
+
162
+ Create your issues.
163
+
164
+ ```bash
165
+ cannon fire # run using cannon.config.json
166
+ cannon fire --preview # dry run — nothing created, no delays
167
+ cannon fire --unsafe # no delays (fast but risky)
168
+ cannon fire --delay 2 # fixed 2-minute delay between issues
169
+ cannon fire --fresh # ignore saved progress, start over
170
+
171
+ # override source without editing config
172
+ cannon fire -s csv -f ./issues.csv
173
+ cannon fire -s json -f ./issues.json --preview
174
+ cannon fire -s docx -f ./issues.docx --delay 1
175
+ cannon fire -s pdf -f ./issues.pdf --unsafe
176
+ ```
177
+
178
+ | Flag | What it does |
179
+ | ---------------- | ------------------------------------------------------- |
180
+ | `--preview` | Dry run — shows what would be created, skips all delays |
181
+ | `--unsafe` | No delays at all — fast but GitHub may flag as spam |
182
+ | `--delay <mins>` | Fixed delay in minutes, e.g. `--delay 2` |
183
+ | `--fresh` | Ignore saved progress and start from the beginning |
184
+ | `-s <type>` | Source type override |
185
+ | `-f <path>` | Source file override |
186
+ | `-q <sql>` | SQL query override (database sources) |
187
+
188
+ ---
189
+
190
+ ## Safe Mode vs Unsafe Mode
191
+
192
+ | | Safe (`safeMode: true`) | Unsafe (`safeMode: false`) |
193
+ | ---------------- | -------------------------- | -------------------------- |
194
+ | Delays | Random, 4–8 min by default | None |
195
+ | GitHub spam risk | Low | High |
196
+ | Recommended for | All real runs | Testing only |
197
+
198
+ Safe mode is on by default. For large batches never turn it off.
199
+
200
+ ---
201
+
202
+ ## Issue Sources
203
+
204
+ Every source needs at minimum: `repo` and `title`.
205
+
206
+ | Field | Required | Description |
207
+ | ----------- | -------- | ----------------------------------------- |
208
+ | `repo` | ✅ | `owner/repo` |
209
+ | `title` | ✅ | Issue title |
210
+ | `body` | — | Description |
211
+ | `labels` | — | Comma-separated: `bug,auth` |
212
+ | `milestone` | — | Auto-created if it doesn't exist |
213
+ | `priority` | — | `HIGH` · `MED` · `LOW` (informational) |
214
+ | `track` | — | e.g. `auth`, `ui`, `docs` (informational) |
215
+
216
+ ### CSV
217
+
218
+ ```csv
219
+ repo,title,body,labels,milestone
220
+ owner/repo,Fix login bug,"Steps to reproduce...",bug,v1.0
221
+ owner/repo,Add dark mode,"User request",enhancement,v1.1
222
+ ```
223
+
224
+ ```json
225
+ "source": { "type": "csv", "file": "./issues.csv" }
226
+ ```
227
+
228
+ ### JSON
229
+
230
+ ```json
231
+ [
232
+ {
233
+ "repo": "owner/repo",
234
+ "title": "Fix login bug",
235
+ "body": "Steps to reproduce...",
236
+ "labels": "bug,auth",
237
+ "milestone": "v1.0"
238
+ }
239
+ ]
240
+ ```
241
+
242
+ ```json
243
+ "source": { "type": "json", "file": "./issues.json" }
244
+ ```
245
+
246
+ ### PDF
247
+
248
+ Two layouts are auto-detected.
249
+
250
+ **Block layout:**
251
+
252
+ ```
253
+ REPO: owner/repo
254
+ TITLE: Fix login bug
255
+ BODY: Steps to reproduce.
256
+ LABELS: bug, auth
257
+ MILESTONE: v1.0
258
+ ```
259
+
260
+ **Table layout** (pipe-separated):
261
+
262
+ ```
263
+ repo | title | body | labels
264
+ owner/repo | Fix login bug | Steps | bug,auth
265
+ ```
266
+
267
+ ```json
268
+ "source": { "type": "pdf", "file": "./issues.pdf" }
269
+ ```
270
+
271
+ ### DOCX
272
+
273
+ A table in your Word file. First row = headers.
274
+
275
+ | repo | title | body | labels |
276
+ | ---------- | ------------- | -------- | -------- |
277
+ | owner/repo | Fix login bug | Steps... | bug,auth |
278
+
279
+ ```json
280
+ "source": { "type": "docx", "file": "./issues.docx" }
281
+ ```
282
+
283
+ ### PostgreSQL
284
+
285
+ ```bash
286
+ # .env
287
+ POSTGRES_URL=postgres://user:password@localhost:5432/mydb
288
+ ```
289
+
290
+ ```json
291
+ "source": {
292
+ "type": "postgres",
293
+ "connectionString": "${POSTGRES_URL}",
294
+ "query": "SELECT repo, title, body, labels, milestone FROM backlog WHERE exported = false"
295
+ }
296
+ ```
297
+
298
+ ### MySQL
299
+
300
+ ```json
301
+ "source": {
302
+ "type": "mysql",
303
+ "connectionString": "${MYSQL_URL}",
304
+ "query": "SELECT repo, title, body, labels FROM issues WHERE status = 'pending'"
305
+ }
306
+ ```
307
+
308
+ ### SQLite
309
+
310
+ ```json
311
+ "source": {
312
+ "type": "sqlite",
313
+ "file": "./backlog.db",
314
+ "query": "SELECT repo, title, body, labels FROM issues"
315
+ }
316
+ ```
317
+
318
+ ---
319
+
320
+ ## Token Security
321
+
322
+ ### Minimum required scope
323
+
324
+ - `public_repo` — if all your repos are public
325
+ - `repo` — if any repo is private
326
+ - Fine-grained PAT — grant only `Issues: Read & Write` + `Metadata: Read` on specific repos
327
+
328
+ ### How the token is stored
329
+
330
+ `cannon auth login` saves your token to `~/.cannon/credentials.json` with `chmod 600` — only your user can read it. It is never written to your project directory.
331
+
332
+ ### Token resolution order
333
+
334
+ ```
335
+ 1. new IssueCannon({ token: '...' }) ← programmatic
336
+ 2. GITHUB_TOKEN env var
337
+ 3. .env file → GITHUB_TOKEN=ghp_xxx
338
+ 4. cannon auth login → ~/.cannon/credentials.json
339
+ 5. cannon.config.json github.token ← last resort, not recommended
340
+ ```
341
+
342
+ ### `.gitignore` — add these
343
+
344
+ ```
345
+ .env
346
+ .cannon_state.json
347
+ cannon-log.json
348
+ ```
349
+
350
+ `cannon.config.json` is safe to commit as long as `github.token` is blank.
351
+
352
+ ---
353
+
354
+ ## Programmatic Usage
355
+
356
+ ```js
357
+ import { IssueCannon } from '@alien-protocol/cannon';
358
+
359
+ const cannon = new IssueCannon({
360
+ safeMode: true,
361
+ dryRun: false,
362
+ });
363
+
364
+ const { created, failed } = await cannon.fire({
365
+ source: 'csv',
366
+ file: './issues.csv',
367
+ });
368
+
369
+ console.log(`Created: ${created.length} Failed: ${failed.length}`);
370
+ ```
371
+
372
+ ---
373
+
374
+ ## Roadmap
375
+
376
+ | Feature | Description |
377
+ | ------------------------- | --------------------------------------------------------------------------------- |
378
+ | `cannon retry` | Re-run only the failed issues from the last batch |
379
+ | Issue templates | Define a `bodyTemplate` in config with `{{variables}}` per issue |
380
+ | Webhook notify | POST a summary to Slack/Discord/Teams on completion _(config ready, coming soon)_ |
381
+ | `cannon serve` | Local web dashboard with live progress and retry button |
382
+ | Fuzzy duplicate detection | Catch near-duplicate titles, not just exact matches |
383
+ | Milestone auto-close | Auto-close milestones once all their issues are created |
384
+ | AI issue enhancement | Improve titles and bodies via Anthropic API before creating |
385
+ | GitHub App auth | Org-wide auth without individual user tokens |
386
+
387
+ ---
388
+
389
+ ## Maintainer
390
+
391
+ [ryzen-xp](https://github.com/ryzen-xp)
392
+
393
+ ## License
394
+
395
+ MIT