Skip to content

Add gh-ext-issue-sync: GitHub CLI extension for syncing issues#1

Merged
nsheaps merged 5 commits intomainfrom
claude/gh-ext-issue-sync-VD8Vs
Mar 24, 2026
Merged

Add gh-ext-issue-sync: GitHub CLI extension for syncing issues#1
nsheaps merged 5 commits intomainfrom
claude/gh-ext-issue-sync-VD8Vs

Conversation

@nsheaps
Copy link
Copy Markdown
Owner

@nsheaps nsheaps commented Mar 24, 2026

This PR introduces gh-ext-issue-sync, a complete GitHub CLI extension that enables syncing GitHub issues to local markdown files with YAML frontmatter, and pushing local changes back to GitHub.

Summary

The extension provides three main commands:

  • pull: Download issues from GitHub as local markdown files
  • push: Upload local changes back to GitHub
  • status: Compare local files against GitHub to show what's modified

Issues are stored as markdown files with YAML frontmatter containing metadata (title, state, labels, assignees, milestone, etc.), allowing users to edit issues offline in their favorite editor, track changes in git, and perform bulk operations.

Key Changes

Core Architecture:

  • internal/sync/client.go: Client interface abstraction for testability
  • internal/sync/github.go: GHClient implementation using gh CLI for all GitHub operations
  • internal/sync/issue.go: Issue and IssueFrontmatter types
  • internal/sync/push.go: Push logic with milestone title-to-number resolution and caching

Commands:

  • cmd/root.go: Root command setup with injectable client for testing
  • cmd/pull.go: Pull single or all issues with state filtering
  • cmd/push.go: Push single or all issues with dry-run support
  • cmd/status.go: Compare local files against remote, showing modified/synced/missing issues

File Format:

  • internal/frontmatter/frontmatter.go: Generic YAML frontmatter marshal/unmarshal for markdown files
  • Supports round-trip serialization of metadata + body content

Testing:

  • cmd/cmd_test.go: Comprehensive command tests using mock client (532 lines)
    • Tests for pull/push/status commands
    • Error handling and validation
    • Dry-run functionality
    • Mutual exclusion checks
  • internal/sync/github_test.go: API conversion tests
  • internal/sync/push_test.go: Push validation tests
  • internal/frontmatter/frontmatter_test.go: Frontmatter serialization tests

Build & CI:

  • mise.toml: Tool versions (Go 1.24, gh CLI, prettier)
  • mise/tasks/: Build, test, lint, check tasks
  • .github/workflows/ci.yaml: CI pipeline (build, test, coverage, lint)
  • .github/workflows/release.yaml: Release workflow with precompiled binaries

Documentation:

  • README.md: Comprehensive user guide with examples, file format spec, and development setup
  • CLAUDE.md: Developer context and architecture notes

Notable Implementation Details

  • Testability: Client interface allows injecting mock implementations; all commands use dependency injection
  • Milestone Resolution: Milestone titles are resolved to numbers on push with caching to avoid repeated API calls
  • Pagination: Handles paginated GitHub API responses for fetching all issues
  • Validation: Comprehensive input validation (positive issue numbers, non-empty titles, valid states)
  • Dry-run: Push command supports --dry-run flag to preview changes without applying them
  • File Format: Zero-padded filenames (00042.md) for consistent sorting; YAML frontmatter with markdown body
  • Status Comparison: Detects changes in title, body, state, labels, assignees, and milestone

https://claude.ai/code/session_01QbMEyYmqunBE6ABt28GDka

claude added 5 commits March 23, 2026 08:07
Set up the complete project skeleton for gh-ext-issue-sync:
- Go module with cobra CLI (pull, push, status subcommands)
- Internal packages for issue sync logic and frontmatter handling
- Mise tasks for build, test, lint, check, setup
- CI workflow (build + test + lint) and release workflow
- Prettier config, editorconfig, gitignore matching nsheaps org patterns

https://claude.ai/code/session_01QbMEyYmqunBE6ABt28GDka
- Pull fetches issues via gh API and writes markdown files with YAML frontmatter
- Push reads local files and updates GitHub issues via PATCH
- Status compares local files against remote and reports diffs
- Frontmatter package handles marshal/unmarshal with round-trip tests
- Supports --all flag for batch operations, --state filter, --dir for output

https://claude.ai/code/session_01QbMEyYmqunBE6ABt28GDka
…ensive tests

- Extract sync.Client interface to decouple commands from gh CLI, enabling testability
- Fix order-dependent label/assignee comparison in status (now sorted)
- Add milestone comparison to status command
- Add milestone resolution in push (title -> number lookup)
- Filter pull requests from issue listing (GitHub API returns PRs as issues)
- Fix pagination: use --jq '.[]' with streaming JSON decoder for gh api --paginate
- Add input validation (positive issue numbers, non-empty titles)
- Add partial-failure handling in push --all (continues on errors, reports summary)
- Add comprehensive tests: 18 test cases covering pull/push/status/validation
- Test coverage: cmd 78.6%, frontmatter 82.6%, sync 18% (GH API calls untestable)

https://claude.ai/code/session_01QbMEyYmqunBE6ABt28GDka
- README: why section, quick start, full command reference with flags table
- README: file format spec with editable-field documentation
- README: practical examples (bulk-close, add labels, git tracking)
- README: development guide with project structure and architecture overview
- CLAUDE.md: updated with architecture decisions and new file layout
- LICENSE: MIT
- CI: add coverage reporting to test step
- mise/tasks/test: add -cover flag

https://claude.ai/code/session_01QbMEyYmqunBE6ABt28GDka
Review iteration targeting categories below 85%:

Security (84 → 88):
- Add context timeouts (2min default, 5min for paginated) to all exec.Command calls
- Add state validation (must be "open" or "closed") on push

Usability (85 → 90):
- Make --all and issue number mutually exclusive (clear error instead of silent ignore)
- Add --dry-run flag to push command for safe preview
- Add status summary line ("All N issues in sync" or "N synced, N modified, N errors")
- Improve milestone resolution errors with list of available milestones

Test quality (80 → 85):
- Add push validation tests (invalid number, empty title, invalid state)
- Add dry-run test (verifies no API calls made)
- Add mutual exclusion tests for pull and push

Flexibility (82 → 86):
- Add milestone caching to avoid N API calls for batch pushes with same milestone

Documentation:
- Add Troubleshooting section to README (auth errors, milestone resolution, batch failures)
- Add Known Limitations section (no comments sync, no conflict detection, PR filtering)
- Add package-level doc comments to sync and frontmatter packages

https://claude.ai/code/session_01QbMEyYmqunBE6ABt28GDka
@nsheaps nsheaps merged commit 0a5a906 into main Mar 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants