diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-06 23:53:52 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-06 23:53:52 -0500 |
| commit | fef03a1f4f19c45a31928989aecb4ff8a47cea4a (patch) | |
| tree | 88ad9fa1dad62f4d63f2f3ad0b65a14b39d9079f /scripts/README.org | |
| parent | 4a4b1bc974a3fdb4d88af3ee575786ca363696e2 (diff) | |
| download | pearl-fef03a1f4f19c45a31928989aecb4ff8a47cea4a.tar.gz pearl-fef03a1f4f19c45a31928989aecb4ff8a47cea4a.zip | |
feat(scripts): import an org backlog into the Pearl workspace
I had 44 open tasks in the org backlog and no way to get them into Linear short of typing each one in by hand. This adds a script that reads the level-2 TODO/DOING headings under the "Pearl Open Work" section and creates one issue per task.
The priority cookie maps to Linear priority, a [#D] "someday" task lands in Icebox and the rest in Backlog, tags become labels (missing ones created), and the heading body becomes the description. The discuss/next/cleanup/pearl workflow tags are dropped rather than turned into labels. It skips a task whose title already exists, so a re-run only fills in what's missing, and the two umbrella headings plus the Resolved section are left out.
Same shape as the seed script: a pure parser and mapper with no I/O, behind a thin GraphQL client that's the only network boundary, so a fake transport routing on the operation name covers the import end to end. 8 tests across parse, mapping, and the import flow.
Diffstat (limited to 'scripts/README.org')
| -rw-r--r-- | scripts/README.org | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/scripts/README.org b/scripts/README.org index e6bacd2..5d5ab6d 100644 --- a/scripts/README.org +++ b/scripts/README.org @@ -82,6 +82,62 @@ the repo. A convenient way to pass it: default new-issue state at Triage (the intake column) after the columns reconcile, so a fresh issue lands there. +* import_org_backlog.py + +** Purpose + +Imports an org-mode backlog into the Pearl Linear workspace. It reads the +level-2 =TODO=/=DOING= headings under the "Pearl Open Work" section and creates +one Linear issue per task, carrying the priority, tags, and body across. + +The mapping: + +- priority cookie =[#A]= .. =[#D]= becomes Linear priority Urgent .. Low, +- a =[#D]= "someday" task lands in Icebox, everything above it in Backlog, +- tags become labels (missing ones are created); the =discuss=, =next=, + =cleanup=, and =pearl= workflow markers are dropped rather than turned into + labels, +- the heading body becomes the issue description, minus the property drawer and + any sub-entries. + +It's idempotent: a task whose title already exists is skipped, so a re-run only +fills in what's missing. The two umbrella headings (the dogfooding parent and +the manual-testing checklist) and everything under the Resolved section are left +out. + +** Usage + +The script reads the Linear API key from =LINEAR_API_KEY= and takes the org file +as its argument. + +#+begin_src bash + # preview the tasks without creating anything + python3 scripts/import_org_backlog.py todo.org --dry-run + + # run it + LINEAR_API_KEY="$(tr -d '[:space:]' < apikey.txt)" python3 scripts/import_org_backlog.py todo.org +#+end_src + +Run the tests with pytest: + +#+begin_src bash + pytest scripts/tests/test_import_org_backlog.py +#+end_src + +** Notes + +- *Dry-run first.* =--dry-run= parses the file and prints each task with its + target state and surviving labels, plus the full label set it would create. It + touches the network only on a real run, so it's the safe way to confirm scope + before importing. + +- *Idempotent by title.* The skip check matches on exact issue title. Editing a + task's title in the org file and re-running creates a second issue rather than + updating the first, so treat titles as stable once imported. + +- *Tags are matched case-insensitively.* An existing =Bug= label is reused for a + =:bug:= tag; only genuinely new labels are created. + * coverage-summary.el ** Purpose |
