Skip to content

create-issues: set board Status (and Priority/Size) on added items #1

Description

@lipex360x

Goal

create-issues adds each new issue to the linked Projects v2 board but leaves the Status field empty, so every card lands in "No Status" (outside every column). Set a default Status (and map the P* and size labels to the Priority/Size fields) when adding an item, so cards land categorized.

Symptom

After gh-toolkit create-issues <owner/repo> <issues.json> on a repo linked to a board, the issues appear as board items but all sit under "No Status". The Priority and Size single-select fields are also empty, even though the issue labels carry that data (P0, M, etc).

Reproduced on lipex360x/ledgerflow (2026-06-06): 8 issues created, all 8 in "No Status", Priority/Size blank.

Root cause

scripts/create-issues.sh, function add_to_board() (around lines 104-118): it runs the addProjectV2ItemById mutation but pipes the result to /dev/null, discarding the returned item.id. It never calls updateProjectV2ItemFieldValue, so no field is set. The item is added with empty Status/Priority/Size.

Fix path (chosen)

Extend add_to_board() (or add a sibling set_board_fields()):

  1. Capture the item.id returned by addProjectV2ItemById (stop discarding it).
  2. Query the linked project once for the Status, Priority, Size single-select field ids and their option ids (GraphQL projectV2.fields -> ProjectV2SingleSelectField). Cache for the run.
  3. Set Status to Backlog via updateProjectV2ItemFieldValue.
  4. Map the issue's labels to fields, best-effort: P0|P1|P2 -> Priority; XS|S|M|L|XL -> Size.
  5. Best-effort and idempotent: if a field or option does not exist on that project, skip it silently (a project without a Size field must not break). Keep board work non-fatal to the exit code, matching the current contract (issue creation is the primary contract).

Default Status is Backlog (the entry column). Rejected alternative: leaving Status configurable via a flag now. That is scope creep; a fixed Backlog default solves the reported bug, and a --default-status flag can be a later issue if needed.

Implementation order (TDD)

Tests are bats with a PATH-injected gh mock (per this repo's CLAUDE.md). Land as separate commits. Use chained assertions (&& \).

  1. Red - in tests/create-issues.bats, extend the gh mock to record GraphQL mutation calls to a log file, and add a test asserting that after create-issues, the recorded calls include an updateProjectV2ItemFieldValue setting Status to the Backlog option for the created item. Commit: test: create-issues sets board Status (failing). Confirm it fails because no such mutation is issued today (not a mock wiring error).
  2. Green - implement field-setting in create-issues.sh until the test passes. Add the Priority/Size mapping with their own assertions. Commit: feat: create-issues sets Status/Priority/Size on board items.
  3. Refactor - extract the field-resolution helper if it bloats add_to_board; keep tests green. Commit: refactor: extract board field resolution.

Also extend the dry-run so the omission is visible in preview (see AC): the dry-run currently exits before any board logic (lines 66-73) and prints only DRY_RUN:issue/<title>. Make it also print the intended fields, for example DRY_RUN:issue/<title>:status=Backlog,priority=P0,size=M.

Files to touch

File What changes
scripts/create-issues.sh capture item id; resolve field/option ids; set Status + map Priority/Size; extend dry-run output
tests/create-issues.bats mock records GraphQL mutations; assert Status/Priority/Size set; assert dry-run prints intended fields
README.md document board field behaviour
SKILL.md note that create-issues sets Status=Backlog and maps Priority/Size

Acceptance criteria

Tick each item by editing this issue body (gh issue edit 1) as you land the corresponding commit. Do not batch ticks at the end.

  • Created issues land in the Backlog column, not "No Status"
  • P0/P1/P2 labels set the board Priority field; XS..XL set Size
  • Missing field or option on a project is skipped silently (no failure, no exit-code change)
  • Dry-run prints the intended fields per issue (for example DRY_RUN:issue/<title>:status=Backlog,priority=P0,size=M)
  • Regression test was written red first and now passes
  • Board work stays non-fatal: a field-set failure logs a WARN to stderr and does not change the exit code
  • Quality gates pass: bats tests/; chained-assert audit prints nothing; shellcheck -x install.sh scripts/*.sh lib/*.sh bin/gh-toolkit tests/*.bats clean

Out of scope

  • A configurable --default-status flag (separate issue if wanted).
  • Backfilling Status on issues created before this fix (one-off, not part of the script contract).
  • Changing the shared single "Board" project model.

Constraints (from this repo's conventions)

  • Bash 3.2 compatible: guard array access with ${#arr[@]} before iterating.
  • Output contract: any FAILED line goes to stdout; logs and WARN go to stderr via log::*.
  • Bats: chain assertions with && \; keep setup statements unchained.
  • Never use --no-verify. Never add a non-bash runtime.

Branch

git checkout main && git pull
git checkout -b fix/board-status-fields-1

Open the PR with Closes #1.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions