GitHub Issues

The GitHub connector provides four commands:

  • ubconnect github from-github: import issues from GitHub into a Sphinx-Needs needs.json.

  • ubconnect github to-github: create GitHub issues from selected needs and patch the source RST with the new issue numbers.

  • ubconnect github validate-issue-refs: cross-check :issue: references on existing needs against the GitHub issue tracker.

  • ubconnect github sync-issue-refs: reconcile GitHub sub-issues into the :issue: lists of the needs that own them.

Note

The github connector requires an active ubConnect license. See License configuration for activation instructions.

Authentication

The connector reads its personal access token from the GH_TOKEN environment variable, falling back to GITHUB_TOKEN. There is no TOML field for the token.

The token must be a GitHub Personal Access Token with the following scope:

  • repo — for private repositories.

  • public_repo — sufficient for public repositories only.

Fine-grained PATs work with the equivalent Issues: Read permission.

from-github

Imports issues into a Sphinx-Needs-compatible needs.json. Each imported issue produces a primary need carrying an :issue: field set to its GitHub issue number, so the output can be validated directly with validate-issue-refs.

$ ubconnect github from-github --config ubproject.toml

The config declares where to import from and how to shape the output; per-run what to import (milestone, labels, a named set of issues) is supplied via CLI flags so one config can drive many imports.

Filter flags (from-github)

Flag

Effect

--milestone TEXT

Limit the import to issues in this milestone (matched by title; accepts * for any, none for none, or a numeric milestone id to bypass title resolution).

--label TEXT

Limit the import to issues carrying this label. Repeat the flag to require multiple labels (GitHub’s AND semantics).

--issue TEXT

Import only the named issues. Each value is either an issue number (42) or a GitHub issue URL (https://github.com/owner/name/issues/42). Repeat the flag to pick multiple. When ``–issue`` is set, --milestone and --label are ignored — the explicit list of issues wins.

Examples:

# Import all issues in milestone "v1.0" labelled both "bug" and "P1"
$ ubconnect github from-github -c ubproject.toml \
    --milestone v1.0 --label bug --label P1

# Import three specific issues by number / URL
$ ubconnect github from-github -c ubproject.toml \
    --issue 1001 \
    --issue https://github.com/owner/name/issues/1005 \
    --issue 1009

Configuration

[ubconnect.from_github_issues]
repo = "owner/name"
requirements_section_aliases = ["Acceptance Criteria"]
outdir = "_build"
id_prefix = "GH_"
timeout_seconds = 30

Configuration options:

Field

Type

Default

Description

repo

string

required

Repository in owner/name form.

requirements_section_aliases

list[string]

["Acceptance Criteria"]

Markdown headings (case-folded) that mark a section whose bullets become comp_req needs. When no matching heading exists in the issue body, the issue maps 1:1 to a single feat need.

outdir

path

directory of config file

Output directory for needs.json.

id_prefix

string

"GH_"

Prefix for emitted need ids (issue number is appended).

timeout_seconds

int

30

Per-request HTTP timeout for the GitHub API.

Consuming the output in Sphinx-Needs

from-github writes a Sphinx-Needs needs.json. To render it, import it into a Sphinx-Needs build with the needimport directive.

The consuming project’s conf.py must declare three things: the need types the connector emits, the satisfies link, and the provenance fields written onto every need. Two of those fields are not strings. issue is an integer (the GitHub issue number, read back by validate-issue-refs) and github_labels is an array, so they must be declared with typed needs_fields (Sphinx-Needs 8). A plain string-only needs_extra_options declaration is not sufficient.

# conf.py
extensions = ["sphinx_needs"]

# One entry per type the connector emits. With the default
# configuration that is "req" for issues and "spec" for bullets.
# Adjust to match fallback_type, bullet_type and type_mapping.
needs_types = [
    {"directive": "req", "title": "Requirement", "prefix": "R_",
     "color": "#BFD8D2", "style": "node"},
    {"directive": "spec", "title": "Specification", "prefix": "S_",
     "color": "#FEDCD2", "style": "node"},
]

needs_links = {
    "satisfies": {"incoming": "satisfied by", "outgoing": "satisfies"},
}

needs_fields = {
    "content_format": {"schema": {"type": "string"}},
    "issue": {"schema": {"type": "integer"}},
    "github_url": {"schema": {"type": "string"}},
    "github_author": {"schema": {"type": "string"}},
    "github_labels": {"schema": {"type": "array",
                                 "items": {"type": "string"}}},
}

Import the file and render it from any document:

.. needimport:: needs.json

.. needtable::
   :columns: id, title, type, satisfies
   :style: table

Warning

If the provenance fields are not declared as typed needs_fields, needimport drops every need that carries them. The drop is silent: there is no error and no warning. The only visible symptom is unknown outgoing link warnings for the satisfies links whose target needs were dropped.

validate-issue-refs

Cross-checks :issue: extra fields on existing needs against the GitHub issue tracker. Reports issues that:

  • 404 (do not exist or are inaccessible) as failures (exit code 1).

  • Are closed on GitHub while the referencing need is still open as warnings (exit code 0 by default; promoted to 1 with --strict).

$ ubconnect github validate-issue-refs --config ubproject.toml
$ ubconnect github validate-issue-refs --config ubproject.toml --strict

Flags (validate-issue-refs)

Flag

Effect

--strict

Promote closed-issue warnings to failures (exit code 1).

--allow-coverage-gap

Do not exit with code 1 when some needs have no :issue: reference at all. By default, needs without any :issue: value cause a failure so every need is traceable.

--sync

Also report DRIFT: GitHub sub-issues that exist under a tracked parent but are absent from the :issue: list. Emits a WARN line per missing number. Does not affect the exit code; use it to spot tracking gaps without breaking CI.

Configuration

[ubconnect.validate_github_issues]
repo = "owner/name"
needsjson_path = "_build/needs.json"
open_status_values = ["open", "in_progress"]
timeout_seconds = 30

[ubconnect.validate_github_issues.lifecycle]
done_status = ["implemented", "verified"]

Configuration options:

Field

Type

Default

Description

repo

string

required

Repository in owner/name form.

needsjson_path

path

required

Path to the needs.json file to validate.

open_status_values

list[string]

["open", "in_progress"]

Need status values considered “still open” when comparing against a closed GitHub issue.

timeout_seconds

int

30

Per-request HTTP timeout for the GitHub API.

lifecycle.done_status

string or list[string]

not set

When all GitHub issues linked to a need are closed but the need’s status is not in this list, the command emits a LIFECYCLE WARN. Accepts a single string or a list. Leave unset to skip lifecycle checks entirely.

to-github

Creates GitHub issues from selected needs. One issue is created per matched need by default. After creation the command patches the source RST file in place, appending the new issue number to the need’s :issue: field so the document stays in sync with the tracker.

$ ubconnect github to-github -c ubproject.toml \
    --needsjson _build/needs.json \
    --need REQ_001 --need REQ_002

# Dry run: print what would be created without touching GitHub or RST
$ ubconnect github to-github -c ubproject.toml \
    --needsjson _build/needs.json \
    --need "REQ_*" --dry

Flags (to-github)

Flag

Effect

-c / --config PATH

Path to the TOML config file. Required.

--needsjson PATH

Path to the needs.json to read needs from. Required.

--need TEXT

Need id or fnmatch glob to select needs for creation. Repeat to select multiple. Examples: REQ_001, REQ_*, SPEC_001[ab]. At least one --need is required.

--label TEXT

Label to apply to every created issue. Repeat for multiple labels. Labels must already exist in the repository.

--allow-duplicate

Create a new issue even when the need already carries an :issue: number. By default the command skips needs that already have a linked issue.

--dry

Print what would be created (title, body preview, labels) but do not call the GitHub API and do not modify any RST file.

Configuration

[ubconnect.to_github_issues]
repo = "owner/name"
template_path = ".github/ISSUE_TEMPLATE/feature.md"
content_marker = "Description"
timeout_seconds = 30

Configuration options:

Field

Type

Default

Description

repo

string

required

Repository in owner/name form.

template_path

path

not set

Path to a GitHub issue template (Markdown). When set, the need’s content is inserted after the heading named by content_marker. When unset, a minimal title-and-body issue is created.

content_marker

string

"Description"

Heading text under which the need’s content is inserted when template_path is configured. The ## Markdown prefix is added automatically; set this to the heading text only (e.g. Description, not ## Description).

timeout_seconds

int

30

Per-request HTTP timeout for the GitHub API.

RST patching

After each successful issue creation the command performs an atomic write to the source RST file that defines the need, appending the new issue number to the :issue: field. The patch is applied before the next issue is created so a partial run leaves the RST consistent with what was actually created on GitHub.

sync-issue-refs

Reconciles native GitHub sub-issues into the :issue: lists of the needs that own them. For each need that already has a :issue: value, the command fetches any sub-issues linked under that parent on GitHub and patches the source RST file with the discovered numbers.

This is useful when issues are created or linked directly in GitHub rather than through to-github, and you want the RST to stay in sync without running a full validate-issue-refs cycle first.

$ ubconnect github sync-issue-refs --config ubproject.toml

Flags (sync-issue-refs)

Flag

Effect

-c / --config PATH

Path to the TOML config file. Required.

Configuration

sync-issue-refs reuses the [ubconnect.validate_github_issues] config section. No separate section is needed.

[ubconnect.validate_github_issues]
repo = "owner/name"
needsjson_path = "_build/needs.json"
timeout_seconds = 30

:issue: field schema

The :issue: extra field is now a list of integers. A single integer value is still accepted when reading existing needs files so that documents authored before this change continue to work. Going forward, author :issue: as a list even when there is only one linked issue:

.. req:: My requirement
   :id: REQ_001
   :issue: [42]

.. req:: Requirement linked to two issues
   :id: REQ_002
   :issue: [42, 99]

Declare the field in conf.py as an array so Sphinx-Needs stores it correctly:

needs_fields = {
    "issue": {"schema": {"type": "array", "items": {"type": "integer"}}},
}