From e1813a396ed5f65d973dde9634d7aac63a38c140 Mon Sep 17 00:00:00 2001 From: Fatima367 <170196704+Fatima367@users.noreply.github.com> Date: Sun, 12 Apr 2026 16:09:57 +0500 Subject: [PATCH] feat: add GitHub Issues Integration extension Add community extension that generates spec artifacts from GitHub Issues, eliminating duplicate work between issue tracking and SDD. Features: - /speckit.github-issues.import - Import GitHub Issue and generate spec.md - /speckit.github-issues.sync - Keep specs updated with issue changes - /speckit.github-issues.link - Add bidirectional traceability Resolves #2175 --- spec-kit-github-issues/.extensionignore | 43 +++ spec-kit-github-issues/CHANGELOG.md | 36 ++ spec-kit-github-issues/LICENSE | 21 ++ spec-kit-github-issues/README.md | 345 ++++++++++++++++++ spec-kit-github-issues/commands/import.md | 242 ++++++++++++ spec-kit-github-issues/commands/link.md | 244 +++++++++++++ spec-kit-github-issues/commands/sync.md | 243 ++++++++++++ spec-kit-github-issues/extension.yml | 45 +++ .../github-issues-config.template.yml | 41 +++ 9 files changed, 1260 insertions(+) create mode 100644 spec-kit-github-issues/.extensionignore create mode 100644 spec-kit-github-issues/CHANGELOG.md create mode 100644 spec-kit-github-issues/LICENSE create mode 100644 spec-kit-github-issues/README.md create mode 100644 spec-kit-github-issues/commands/import.md create mode 100644 spec-kit-github-issues/commands/link.md create mode 100644 spec-kit-github-issues/commands/sync.md create mode 100644 spec-kit-github-issues/extension.yml create mode 100644 spec-kit-github-issues/github-issues-config.template.yml diff --git a/spec-kit-github-issues/.extensionignore b/spec-kit-github-issues/.extensionignore new file mode 100644 index 000000000..c53d5c509 --- /dev/null +++ b/spec-kit-github-issues/.extensionignore @@ -0,0 +1,43 @@ +# Editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +Thumbs.db + +# Test files +tests/ +test_*.py +*_test.py + +# Development files +.git/ +.github/ +.gitignore + +# Build artifacts +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +dist/ +build/ +*.egg-info/ + +# Documentation source +docs/source/ +docs/drafts/ + +# Local config (users should use the template) +*-config.yml +!*-config.template.yml + +# Temporary files +*.tmp +*.bak +.*.swp diff --git a/spec-kit-github-issues/CHANGELOG.md b/spec-kit-github-issues/CHANGELOG.md new file mode 100644 index 000000000..dbb932dd7 --- /dev/null +++ b/spec-kit-github-issues/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +All notable changes to the GitHub Issues Integration extension will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.0] - 2026-04-12 + +### Added + +- Initial release of GitHub Issues Integration extension +- `/speckit.github-issues.import` command to import GitHub Issues and generate spec.md +- `/speckit.github-issues.sync` command to sync spec artifacts with issue updates +- `/speckit.github-issues.link` command to add bidirectional traceability +- Configuration file support for customizing behavior +- Automatic parsing of issue sections (problem, solution, alternatives) +- Comment preservation in spec Discussion Notes +- Label integration as spec tags +- Issue state tracking (open/closed) +- Metadata file (`.issue-link`) for tracking linked issues +- Comprehensive documentation and examples + +### Features + +- Import issues from any GitHub repository +- Support for both `owner/repo#123` and `#123` formats +- Automatic detection of current repository +- Bidirectional linking between specs and issues +- Sync detection based on issue update timestamps +- Batch sync for all linked issues +- Selective sync for specific features or issues +- User confirmation before applying updates +- Graceful error handling and permission checks + +[1.0.0]: https://github.com/Fatima367/spec-kit-github-issues/releases/tag/v1.0.0 diff --git a/spec-kit-github-issues/LICENSE b/spec-kit-github-issues/LICENSE new file mode 100644 index 000000000..3edf2996f --- /dev/null +++ b/spec-kit-github-issues/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Fatima367 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/spec-kit-github-issues/README.md b/spec-kit-github-issues/README.md new file mode 100644 index 000000000..83e8dc34f --- /dev/null +++ b/spec-kit-github-issues/README.md @@ -0,0 +1,345 @@ +# GitHub Issues Integration Extension + +A Spec Kit extension that generates spec artifacts from GitHub Issues, eliminating duplicate work between issue tracking and Specification-Driven Development (SDD). + +## Problem + +Developers already document requirements in GitHub Issues (user stories, acceptance criteria, labels, discussions) but then rewrite everything from scratch in `spec.md` when starting Specification-Driven Development. This creates: + +- **Duplicate work** - Writing the same information twice +- **Context loss** - Losing valuable discussion and rationale from issues +- **Sync drift** - Issues and specs diverge over time +- **Manual overhead** - Copying and reformatting content manually + +## Solution + +This extension provides three commands that bridge GitHub Issues and Spec Kit: + +1. **`/speckit.github-issues.import`** - Import a GitHub Issue and generate structured `spec.md` +2. **`/speckit.github-issues.sync`** - Keep specs updated when source issues change +3. **`/speckit.github-issues.link`** - Add bidirectional traceability between specs and issues + +## Features + +- ✅ **Import GitHub Issues** - Convert issues to structured spec.md files +- ✅ **Structured parsing** - Extract problem statements, solutions, acceptance criteria +- ✅ **Include discussions** - Preserve valuable comments and context +- ✅ **Bidirectional links** - Maintain traceability between issues and specs +- ✅ **Automatic sync** - Keep specs updated when issues change +- ✅ **Label integration** - Import issue labels as spec tags +- ✅ **Status tracking** - Monitor issue state (open/closed) + +## Installation + +### Prerequisites + +- Spec Kit installed (`specify` CLI) +- GitHub CLI (`gh`) installed and authenticated +- Git repository initialized + +### Install Extension + +```bash +# From your spec-kit project directory +specify extension add github-issues --from https://github.com/Fatima367/spec-kit-github-issues/archive/refs/tags/v1.0.0.zip +``` + +### Verify Installation + +```bash +specify extension list +``` + +You should see: + +``` +✓ GitHub Issues Integration (v1.0.0) + Generate spec artifacts from GitHub Issues + Commands: 3 | Status: Enabled +``` + +### Authenticate with GitHub + +```bash +gh auth login +``` + +## Usage + +### 1. Import a GitHub Issue + +Convert a GitHub Issue into a structured spec.md file: + +```bash +# In your AI agent (e.g., Claude Code) +/speckit.github-issues.import github/spec-kit#2175 + +# Or if you're in the same repository +/speckit.github-issues.import #2175 +``` + +**What it does:** +- Fetches issue title, body, labels, and comments +- Parses structured sections (problem, solution, alternatives) +- Generates `spec.md` with requirements and acceptance criteria +- Creates `.issue-link` metadata for tracking +- Preserves discussion context from comments + +**Output:** +``` +✓ Spec generated at: .specify/specs/001-generate-spec-artifacts/spec.md +✓ Linked to issue: https://github.com/github/spec-kit/issues/2175 + +Next steps: + 1. Review and refine the generated spec + 2. Run /speckit.clarify to fill in any gaps + 3. Run /speckit.plan to create implementation plan + 4. Use /speckit.github-issues.sync to keep spec updated +``` + +### 2. Link Existing Spec to Issue + +Add bidirectional traceability between an existing spec and a GitHub Issue: + +```bash +/speckit.github-issues.link github/spec-kit#2175 +``` + +**What it does:** +- Adds issue reference to spec frontmatter +- Creates `.issue-link` metadata file +- Posts a comment on the GitHub Issue linking back to the spec +- Establishes bidirectional traceability + +**Output:** +``` +✓ Added issue link to spec +✓ Created link metadata +✓ Added traceability comment to issue + +Bidirectional traceability established: + ✓ Spec references issue + ✓ Issue references spec (via comment) +``` + +### 3. Sync Spec with Issue Updates + +Keep your spec synchronized with changes to the source GitHub Issue: + +```bash +# Sync all linked issues +/speckit.github-issues.sync + +# Sync specific feature +/speckit.github-issues.sync 001-feature-name + +# Sync specific issue +/speckit.github-issues.sync #2175 +``` + +**What it does:** +- Detects changes in linked issues (title, body, labels, comments) +- Shows what will be updated +- Prompts for confirmation +- Updates spec with latest issue data +- Appends new comments to Discussion Notes +- Updates metadata timestamps + +**Output:** +``` +Found 1 linked issue(s) +Checking github/spec-kit#2175... + ✓ Updates detected (last synced: 2026-04-10, updated: 2026-04-12) + +The following specs have updates available: + • github/spec-kit#2175 → .specify/specs/001-generate-spec-artifacts/spec.md + +Apply updates? (y/n): y + +Updating .specify/specs/001-generate-spec-artifacts/spec.md... + ✓ Updated title + ✓ Added new comments + ✓ Sync complete +``` + +## Configuration + +Create `.specify/extensions/github-issues/github-issues-config.yml` to customize behavior: + +```yaml +# GitHub repository settings +repository: + owner: "github" + name: "spec-kit" + +# Import settings +import: + include_comments: true + max_comments: 0 # 0 = unlimited + include_labels: true + +# Sync settings +sync: + auto_detect: true + prompt_before_sync: true + +# Link settings +link: + add_to_frontmatter: true + add_to_body: true + link_format: "**Source Issue:** [{repo}#{number}]({url})" + +# Authentication +auth: + use_gh_cli: true +``` + +## Workflow Example + +Here's a complete workflow using this extension: + +```bash +# 1. Initialize spec-kit project +specify init my-project --ai claude + +# 2. Install GitHub Issues extension +specify extension add github-issues + +# 3. Import an issue +/speckit.github-issues.import github/spec-kit#2175 + +# 4. Review and refine the generated spec +/speckit.clarify + +# 5. Create implementation plan +/speckit.plan + +# 6. Generate tasks +/speckit.tasks + +# 7. Implement +/speckit.implement + +# 8. Later, sync with issue updates +/speckit.github-issues.sync +``` + +## Commands Reference + +### `/speckit.github-issues.import` + +**Syntax:** `/speckit.github-issues.import /#` or `/speckit.github-issues.import #` + +**Description:** Import a GitHub Issue and generate structured spec.md + +**Examples:** +```bash +/speckit.github-issues.import github/spec-kit#2175 +/speckit.github-issues.import #2175 +``` + +### `/speckit.github-issues.sync` + +**Syntax:** `/speckit.github-issues.sync [feature-dir|#number]` + +**Description:** Sync spec artifacts with updates from source issues + +**Examples:** +```bash +/speckit.github-issues.sync # Sync all linked issues +/speckit.github-issues.sync 001-feature-name # Sync specific feature +/speckit.github-issues.sync #2175 # Sync specific issue +``` + +### `/speckit.github-issues.link` + +**Syntax:** `/speckit.github-issues.link /#` or `/speckit.github-issues.link #` + +**Description:** Add bidirectional traceability between spec and issue + +**Examples:** +```bash +/speckit.github-issues.link github/spec-kit#2175 +/speckit.github-issues.link #2175 +``` + +## Troubleshooting + +### GitHub CLI not authenticated + +**Error:** `Failed to fetch issue. Check repository access and issue number.` + +**Solution:** +```bash +gh auth login +``` + +### No linked issues found + +**Error:** `No linked issues found. Use /speckit.github-issues.import first.` + +**Solution:** Import an issue first using `/speckit.github-issues.import #` + +### Permission denied when commenting + +**Warning:** `Could not add comment to issue (may lack permissions)` + +**Solution:** Ensure you have write access to the repository. The extension will still create local links. + +### Issue not found + +**Error:** `Invalid format. Use 'owner/repo#123' or '#123'` + +**Solution:** Check the issue number and format. Use full format `owner/repo#123` for external repos. + +## Benefits + +- **Save time** - No more rewriting issue content into specs +- **Preserve context** - Keep valuable discussions and rationale +- **Stay synchronized** - Specs automatically update with issue changes +- **Maintain traceability** - Bidirectional links between issues and specs +- **Reduce errors** - Automated parsing reduces manual transcription mistakes +- **Better collaboration** - Team discussions in issues flow into specs + +## Limitations + +- Requires GitHub CLI (`gh`) installed and authenticated +- Only works with GitHub Issues (not other issue trackers) +- Requires write access to add comments to issues +- Sync is manual (not automatic on issue updates) + +## Contributing + +Contributions are welcome! Please: + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Test thoroughly +5. Submit a pull request + +## License + +MIT License - see [LICENSE](LICENSE) file for details + +## Author + +**Fatima367** +- GitHub: [@Fatima367](https://github.com/Fatima367) +- Repository: [spec-kit-github-issues](https://github.com/Fatima367/spec-kit-github-issues) + +## Acknowledgements + +- Built for [Spec Kit](https://github.com/github/spec-kit) +- Inspired by issue [#2175](https://github.com/github/spec-kit/issues/2175) +- Thanks to the Spec Kit community + +## Version History + +See [CHANGELOG.md](CHANGELOG.md) for version history and release notes. + +## Support + +- **Issues:** [GitHub Issues](https://github.com/Fatima367/spec-kit-github-issues/issues) +- **Discussions:** [GitHub Discussions](https://github.com/Fatima367/spec-kit-github-issues/discussions) +- **Spec Kit:** [Main Repository](https://github.com/github/spec-kit) diff --git a/spec-kit-github-issues/commands/import.md b/spec-kit-github-issues/commands/import.md new file mode 100644 index 000000000..a157ba0ee --- /dev/null +++ b/spec-kit-github-issues/commands/import.md @@ -0,0 +1,242 @@ +--- +description: "Import a GitHub Issue and generate spec.md with structured requirements" +tools: + - 'bash/gh' +--- + +# Import GitHub Issue to Spec + +Import a GitHub Issue (title, body, labels, comments) and generate a structured `spec.md` file with requirements, scenarios, and acceptance criteria. + +## User Input + +$ARGUMENTS + +Expected format: `/#` or just `#` (uses current repo) + +Examples: +- `github/spec-kit#2175` +- `#2175` (if in a GitHub repository) + +## Prerequisites + +1. GitHub CLI (`gh`) must be installed and authenticated +2. You must have read access to the specified repository +3. Run `gh auth login` if not already authenticated + +## Steps + +### 1. Parse Arguments + +Extract the repository owner, name, and issue number from the user input. + +```bash +# Parse input format +input="$ARGUMENTS" + +if [[ "$input" =~ ^#([0-9]+)$ ]]; then + # Format: #123 (use current repo) + issue_number="${BASH_REMATCH[1]}" + repo_info=$(gh repo view --json nameWithOwner -q .nameWithOwner) + repo_owner=$(echo "$repo_info" | cut -d'/' -f1) + repo_name=$(echo "$repo_info" | cut -d'/' -f2) +elif [[ "$input" =~ ^([^/]+)/([^#]+)#([0-9]+)$ ]]; then + # Format: owner/repo#123 + repo_owner="${BASH_REMATCH[1]}" + repo_name="${BASH_REMATCH[2]}" + issue_number="${BASH_REMATCH[3]}" +else + echo "Error: Invalid format. Use 'owner/repo#123' or '#123'" + exit 1 +fi + +echo "Importing issue #$issue_number from $repo_owner/$repo_name" +``` + +### 2. Fetch Issue Data + +Retrieve the issue details using GitHub CLI. + +```bash +# Fetch issue data +issue_data=$(gh issue view "$issue_number" \ + --repo "$repo_owner/$repo_name" \ + --json title,body,labels,comments,author,createdAt,updatedAt,url,state) + +if [ $? -ne 0 ]; then + echo "Error: Failed to fetch issue. Check repository access and issue number." + exit 1 +fi + +# Extract fields +title=$(echo "$issue_data" | jq -r '.title') +body=$(echo "$issue_data" | jq -r '.body // ""') +url=$(echo "$issue_data" | jq -r '.url') +author=$(echo "$issue_data" | jq -r '.author.login') +created_at=$(echo "$issue_data" | jq -r '.createdAt') +state=$(echo "$issue_data" | jq -r '.state') +labels=$(echo "$issue_data" | jq -r '.labels[].name' | paste -sd ',' -) +``` + +### 3. Parse Issue Body + +Extract structured information from the issue body: +- Problem statement +- Proposed solution +- Acceptance criteria +- Alternative approaches + +```bash +# Parse sections from issue body +problem=$(echo "$body" | sed -n '/^[#*]*\s*Problem/,/^[#*]*\s*[A-Z]/p' | sed '$d' | sed '1d') +solution=$(echo "$body" | sed -n '/^[#*]*\s*[Pp]roposed [Ss]olution/,/^[#*]*\s*[A-Z]/p' | sed '$d' | sed '1d') +alternatives=$(echo "$body" | sed -n '/^[#*]*\s*[Aa]lternative/,/^[#*]*\s*[A-Z]/p' | sed '$d' | sed '1d') +``` + +### 4. Process Comments + +Extract relevant information from issue comments. + +```bash +# Get comments +comments=$(echo "$issue_data" | jq -r '.comments[] | "**\(.author.login)** (\(.createdAt)):\n\(.body)\n"') +``` + +### 5. Generate Spec File + +Create a structured `spec.md` file following the spec-kit template format. + +```bash +# Determine feature directory +feature_dir=$(ls -d .specify/specs/*/ 2>/dev/null | tail -1) +if [ -z "$feature_dir" ]; then + # Create new feature + feature_num="001" + feature_name=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed 's/[^a-z0-9-]//g') + feature_dir=".specify/specs/${feature_num}-${feature_name}" + mkdir -p "$feature_dir" +else + # Use existing feature directory + feature_dir="${feature_dir%/}" +fi + +spec_file="$feature_dir/spec.md" +``` + +### 6. Write Spec Content + +Generate the spec.md file with structured content from the issue. + +```markdown +# Feature Specification: $title + +**Source Issue:** [$repo_owner/$repo_name#$issue_number]($url) +**Issue Author:** @$author +**Issue Status:** $state +**Labels:** $labels +**Last Updated:** $(date -u +"%Y-%m-%d") + +## Overview + +$body + +## Problem Statement + +$problem + +## Proposed Solution + +$solution + +## User Stories + + + +### User Story 1: [Title] + +**As a** [user type] +**I want** [goal] +**So that** [benefit] + +**Acceptance Criteria:** +- [ ] Criterion 1 +- [ ] Criterion 2 + +## Functional Requirements + + + +### Requirement 1: [Title] + +**Description:** [Detailed description] + +**Acceptance Criteria:** +- [ ] Criterion 1 +- [ ] Criterion 2 + +## Alternative Approaches Considered + +$alternatives + +## Discussion Notes + + + +$comments + +## Review & Acceptance Checklist + +- [ ] All user stories are clearly defined +- [ ] Acceptance criteria are testable +- [ ] Edge cases are documented +- [ ] Dependencies are identified +- [ ] Success metrics are defined +``` + +### 7. Link Issue to Spec + +Add metadata linking the spec back to the source issue. + +```bash +# Create metadata file +metadata_file="$feature_dir/.issue-link" +cat > "$metadata_file" </#` or just `#` (uses current repo) + +Examples: +- `github/spec-kit#2175` +- `#2175` (if in a GitHub repository) + +## Prerequisites + +1. GitHub CLI (`gh`) must be installed and authenticated +2. You must have write access to the repository to add comments +3. A spec file must exist in the current feature directory + +## Steps + +### 1. Parse Arguments + +Extract the repository owner, name, and issue number from the user input. + +```bash +# Parse input format +input="$ARGUMENTS" + +if [[ "$input" =~ ^#([0-9]+)$ ]]; then + # Format: #123 (use current repo) + issue_number="${BASH_REMATCH[1]}" + repo_info=$(gh repo view --json nameWithOwner -q .nameWithOwner) + repo_owner=$(echo "$repo_info" | cut -d'/' -f1) + repo_name=$(echo "$repo_info" | cut -d'/' -f2) +elif [[ "$input" =~ ^([^/]+)/([^#]+)#([0-9]+)$ ]]; then + # Format: owner/repo#123 + repo_owner="${BASH_REMATCH[1]}" + repo_name="${BASH_REMATCH[2]}" + issue_number="${BASH_REMATCH[3]}" +else + echo "Error: Invalid format. Use 'owner/repo#123' or '#123'" + exit 1 +fi + +repo="$repo_owner/$repo_name" +echo "Linking to issue #$issue_number from $repo" +``` + +### 2. Verify Issue Exists + +Check that the issue exists and is accessible. + +```bash +# Fetch issue data +issue_data=$(gh issue view "$issue_number" \ + --repo "$repo" \ + --json title,url,state) + +if [ $? -ne 0 ]; then + echo "Error: Failed to fetch issue. Check repository access and issue number." + exit 1 +fi + +title=$(echo "$issue_data" | jq -r '.title') +url=$(echo "$issue_data" | jq -r '.url') +state=$(echo "$issue_data" | jq -r '.state') + +echo "Found issue: $title" +``` + +### 3. Find Current Feature Spec + +Locate the spec file in the current feature directory. + +```bash +# Determine current feature directory +current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + +if [[ "$current_branch" =~ ^[0-9]+-(.+)$ ]]; then + # Extract feature name from branch + feature_pattern="${current_branch}" + feature_dir=$(find .specify/specs -maxdepth 1 -type d -name "$feature_pattern" | head -1) +else + # Use most recent feature directory + feature_dir=$(ls -td .specify/specs/*/ 2>/dev/null | head -1) +fi + +if [ -z "$feature_dir" ]; then + echo "Error: No feature directory found. Create a spec first." + exit 1 +fi + +feature_dir="${feature_dir%/}" +spec_file="$feature_dir/spec.md" + +if [ ! -f "$spec_file" ]; then + echo "Error: Spec file not found at $spec_file" + exit 1 +fi + +echo "Found spec: $spec_file" +``` + +### 4. Add Link to Spec + +Update the spec file to include a reference to the source issue. + +```bash +# Check if link already exists +if grep -q "Source Issue.*$repo#$issue_number" "$spec_file"; then + echo "✓ Spec already linked to this issue" +else + # Add source issue link to spec frontmatter + # Find the first heading and insert before it + temp_file=$(mktemp) + + # Read spec and add link after title + awk -v repo="$repo" -v num="$issue_number" -v url="$url" -v state="$state" ' + /^# Feature Specification:/ { + print $0 + print "" + print "**Source Issue:** [" repo "#" num "](" url ")" + print "**Issue Status:** " state + print "**Last Updated:** " strftime("%Y-%m-%d") + next + } + { print } + ' "$spec_file" > "$temp_file" + + mv "$temp_file" "$spec_file" + echo "✓ Added issue link to spec" +fi +``` + +### 5. Create Metadata File + +Create or update the `.issue-link` metadata file. + +```bash +# Create metadata file +metadata_file="$feature_dir/.issue-link" + +cat > "$metadata_file" </dev/null || echo "main") +current_commit=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") + +# Get repository URL +repo_url=$(git config --get remote.origin.url 2>/dev/null | sed 's/\.git$//') +if [[ "$repo_url" =~ ^git@ ]]; then + repo_url=$(echo "$repo_url" | sed 's|^git@github.com:|https://github.com/|') +fi + +# Construct spec URL (if on GitHub) +if [[ "$repo_url" =~ github.com ]]; then + spec_url="$repo_url/blob/$current_branch/$spec_file" +else + spec_url="$spec_file" +fi + +# Create comment body +comment_body="## 📋 Spec-Driven Development + +This issue has been imported into a specification document for structured development. + +**Spec Location:** \`$spec_file\` +**Branch:** \`$current_branch\` +**Spec URL:** $spec_url + +The spec will be kept in sync with this issue using the \`/speckit.github-issues.sync\` command. + +--- +*Generated by [Spec Kit GitHub Issues Extension](https://github.com/github/spec-kit)*" + +# Post comment to issue +gh issue comment "$issue_number" \ + --repo "$repo" \ + --body "$comment_body" + +if [ $? -eq 0 ]; then + echo "✓ Added traceability comment to issue" +else + echo "⚠ Warning: Could not add comment to issue (may lack permissions)" +fi +``` + +### 7. Summary + +Provide a summary of the linking operation. + +```bash +echo "" +echo "Link Summary:" +echo " Issue: $repo#$issue_number" +echo " Title: $title" +echo " Spec: $spec_file" +echo " Metadata: $metadata_file" +echo "" +echo "Bidirectional traceability established:" +echo " ✓ Spec references issue" +echo " ✓ Issue references spec (via comment)" +echo "" +echo "Next steps:" +echo " • Use /speckit.github-issues.sync to keep spec updated with issue changes" +echo " • Continue with /speckit.plan to create implementation plan" +``` + +## Configuration + +Load configuration from `.specify/extensions/github-issues/github-issues-config.yml`: +- `link.add_to_frontmatter`: Add issue link to spec frontmatter +- `link.add_to_body`: Add issue reference to spec body +- `link.link_format`: Format for the link in spec body + +## Error Handling + +- Verify `gh` CLI is installed and authenticated +- Check repository write permissions for commenting +- Handle cases where spec already has a link +- Gracefully handle network errors +- Warn if comment cannot be added but continue with local linking diff --git a/spec-kit-github-issues/commands/sync.md b/spec-kit-github-issues/commands/sync.md new file mode 100644 index 000000000..52e6e5fed --- /dev/null +++ b/spec-kit-github-issues/commands/sync.md @@ -0,0 +1,243 @@ +--- +description: "Sync spec artifacts with updates from the source GitHub Issue" +tools: + - 'bash/gh' +--- + +# Sync Spec with GitHub Issue + +Keep spec artifacts updated when the source GitHub Issue is modified. Detects changes in title, body, labels, and comments, then updates the spec accordingly. + +## User Input + +$ARGUMENTS + +Optional: Specify feature directory or issue number. If not provided, syncs all linked issues in the project. + +Examples: +- `/speckit.github-issues.sync` (sync all linked issues) +- `/speckit.github-issues.sync 001-feature-name` (sync specific feature) +- `/speckit.github-issues.sync #2175` (sync specific issue) + +## Prerequisites + +1. GitHub CLI (`gh`) must be installed and authenticated +2. Spec must have been previously imported using `/speckit.github-issues.import` +3. Issue link metadata must exist (`.issue-link` file) + +## Steps + +### 1. Find Linked Issues + +Discover all specs that are linked to GitHub Issues. + +```bash +# Find all .issue-link files +linked_specs=() +for link_file in .specify/specs/*/.issue-link; do + if [ -f "$link_file" ]; then + linked_specs+=("$link_file") + fi +done + +if [ ${#linked_specs[@]} -eq 0 ]; then + echo "No linked issues found. Use /speckit.github-issues.import first." + exit 0 +fi + +echo "Found ${#linked_specs[@]} linked issue(s)" +``` + +### 2. Parse Arguments + +Determine which specs to sync based on user input. + +```bash +input="$ARGUMENTS" +specs_to_sync=() + +if [ -z "$input" ]; then + # Sync all linked issues + specs_to_sync=("${linked_specs[@]}") +elif [[ "$input" =~ ^#([0-9]+)$ ]]; then + # Sync specific issue number + issue_num="${BASH_REMATCH[1]}" + for link_file in "${linked_specs[@]}"; do + linked_issue=$(grep "^issue_number:" "$link_file" | cut -d' ' -f2) + if [ "$linked_issue" = "$issue_num" ]; then + specs_to_sync+=("$link_file") + fi + done +else + # Sync specific feature directory + feature_dir=".specify/specs/$input" + link_file="$feature_dir/.issue-link" + if [ -f "$link_file" ]; then + specs_to_sync+=("$link_file") + else + echo "Error: No linked issue found for feature: $input" + exit 1 + fi +fi + +if [ ${#specs_to_sync[@]} -eq 0 ]; then + echo "No matching linked issues found." + exit 0 +fi +``` + +### 3. Check for Updates + +For each linked issue, fetch current data and compare with last sync. + +```bash +for link_file in "${specs_to_sync[@]}"; do + feature_dir=$(dirname "$link_file") + spec_file="$feature_dir/spec.md" + + # Read metadata + repo=$(grep "^repository:" "$link_file" | cut -d' ' -f2) + issue_number=$(grep "^issue_number:" "$link_file" | cut -d' ' -f2) + last_synced=$(grep "^last_synced:" "$link_file" | cut -d' ' -f2) + + echo "" + echo "Checking $repo#$issue_number..." + + # Fetch current issue data + issue_data=$(gh issue view "$issue_number" \ + --repo "$repo" \ + --json title,body,labels,comments,updatedAt,state) + + if [ $? -ne 0 ]; then + echo " ✗ Failed to fetch issue data" + continue + fi + + # Check if issue was updated since last sync + updated_at=$(echo "$issue_data" | jq -r '.updatedAt') + + if [[ "$updated_at" > "$last_synced" ]] || [ -z "$last_synced" ]; then + echo " ✓ Updates detected (last synced: $last_synced, updated: $updated_at)" + + # Store for processing + echo "$feature_dir|$repo|$issue_number|$spec_file" >> /tmp/specs_to_update.txt + else + echo " ✓ No updates since last sync" + fi +done +``` + +### 4. Review Changes + +Show what will be updated and prompt for confirmation. + +```bash +if [ ! -f /tmp/specs_to_update.txt ]; then + echo "" + echo "All specs are up to date!" + exit 0 +fi + +echo "" +echo "The following specs have updates available:" +echo "" + +while IFS='|' read -r feature_dir repo issue_number spec_file; do + echo " • $repo#$issue_number → $spec_file" +done < /tmp/specs_to_update.txt + +echo "" +read -p "Apply updates? (y/n): " confirm + +if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + echo "Sync cancelled." + rm /tmp/specs_to_update.txt + exit 0 +fi +``` + +### 5. Apply Updates + +Update each spec with the latest issue data. + +```bash +while IFS='|' read -r feature_dir repo issue_number spec_file; do + echo "" + echo "Updating $spec_file..." + + # Fetch fresh issue data + issue_data=$(gh issue view "$issue_number" \ + --repo "$repo" \ + --json title,body,labels,comments,updatedAt,state,url) + + title=$(echo "$issue_data" | jq -r '.title') + body=$(echo "$issue_data" | jq -r '.body // ""') + state=$(echo "$issue_data" | jq -r '.state') + labels=$(echo "$issue_data" | jq -r '.labels[].name' | paste -sd ',' -) + url=$(echo "$issue_data" | jq -r '.url') + updated_at=$(echo "$issue_data" | jq -r '.updatedAt') + + # Update spec frontmatter + sed -i "s|^**Issue Status:**.*|**Issue Status:** $state|" "$spec_file" + sed -i "s|^**Labels:**.*|**Labels:** $labels|" "$spec_file" + sed -i "s|^**Last Updated:**.*|**Last Updated:** $(date -u +"%Y-%m-%d")|" "$spec_file" + + # Update title if changed + current_title=$(grep "^# Feature Specification:" "$spec_file" | sed 's/^# Feature Specification: //') + if [ "$current_title" != "$title" ]; then + sed -i "s|^# Feature Specification:.*|# Feature Specification: $title|" "$spec_file" + echo " ✓ Updated title" + fi + + # Append new comments to Discussion Notes section + new_comments=$(echo "$issue_data" | jq -r --arg last_synced "$last_synced" \ + '.comments[] | select(.createdAt > $last_synced) | "**\(.author.login)** (\(.createdAt)):\n\(.body)\n"') + + if [ -n "$new_comments" ]; then + # Find Discussion Notes section and append + echo "" >> "$spec_file" + echo "### New Comments (synced $(date -u +"%Y-%m-%d"))" >> "$spec_file" + echo "" >> "$spec_file" + echo "$new_comments" >> "$spec_file" + echo " ✓ Added new comments" + fi + + # Update metadata + link_file="$feature_dir/.issue-link" + sed -i "s|^last_synced:.*|last_synced: $(date -u +"%Y-%m-%dT%H:%M:%SZ")|" "$link_file" + + echo " ✓ Sync complete" + +done < /tmp/specs_to_update.txt + +rm /tmp/specs_to_update.txt +``` + +### 6. Summary + +Provide a summary of the sync operation. + +```bash +echo "" +echo "Sync Summary:" +echo " ✓ All linked issues synced successfully" +echo "" +echo "Next steps:" +echo " 1. Review the updated specs" +echo " 2. Update plan.md if requirements changed significantly" +echo " 3. Update tasks.md if needed" +``` + +## Configuration + +Load configuration from `.specify/extensions/github-issues/github-issues-config.yml`: +- `sync.auto_detect`: Automatically detect changes +- `sync.prompt_before_sync`: Prompt before applying changes + +## Error Handling + +- Verify `gh` CLI is installed and authenticated +- Check that `.issue-link` metadata exists +- Handle network errors gracefully +- Skip specs that fail to update and continue with others +- Preserve original spec content if update fails diff --git a/spec-kit-github-issues/extension.yml b/spec-kit-github-issues/extension.yml new file mode 100644 index 000000000..6cd8a1f3f --- /dev/null +++ b/spec-kit-github-issues/extension.yml @@ -0,0 +1,45 @@ +schema_version: "1.0" + +extension: + id: "github-issues" + name: "GitHub Issues Integration" + version: "1.0.0" + description: "Generate spec artifacts from GitHub Issues - import issues, sync updates, and maintain bidirectional traceability" + author: "Fatima367" + repository: "https://github.com/Fatima367/spec-kit-github-issues" + license: "MIT" + +requires: + speckit_version: ">=0.1.0" + tools: + - name: "gh" + required: true + version: ">=2.0.0" + +provides: + commands: + - name: "speckit.github-issues.import" + file: "commands/import.md" + description: "Import a GitHub Issue and generate spec.md with structured requirements" + + - name: "speckit.github-issues.sync" + file: "commands/sync.md" + description: "Sync spec artifacts with updates from the source GitHub Issue" + + - name: "speckit.github-issues.link" + file: "commands/link.md" + description: "Add bidirectional traceability between spec artifacts and source issue" + + config: + - name: "github-issues-config.yml" + template: "github-issues-config.template.yml" + description: "GitHub Issues integration configuration" + required: false + +tags: + - "integration" + - "github" + - "issues" + - "import" + - "sync" + - "traceability" diff --git a/spec-kit-github-issues/github-issues-config.template.yml b/spec-kit-github-issues/github-issues-config.template.yml new file mode 100644 index 000000000..86ce2e2b5 --- /dev/null +++ b/spec-kit-github-issues/github-issues-config.template.yml @@ -0,0 +1,41 @@ +# GitHub Issues Integration Configuration +# Copy this to github-issues-config.yml and customize + +# GitHub repository settings +repository: + # Default repository owner (can be overridden per command) + owner: "" + # Default repository name (can be overridden per command) + name: "" + +# Import settings +import: + # Include issue comments in the generated spec + include_comments: true + # Maximum number of comments to include (0 = unlimited) + max_comments: 0 + # Include issue labels as tags in spec + include_labels: true + +# Sync settings +sync: + # Automatically detect changes in linked issues + auto_detect: true + # Prompt before applying changes + prompt_before_sync: true + +# Link settings +link: + # Add issue link to spec frontmatter + add_to_frontmatter: true + # Add issue reference to spec body + add_to_body: true + # Link format in spec body + link_format: "**Source Issue:** [{repo}#{number}]({url})" + +# Authentication +# Use GitHub CLI authentication (gh auth login) +# Or set GITHUB_TOKEN environment variable +auth: + # Use gh CLI for authentication (recommended) + use_gh_cli: true