add more opencode goodness
This commit is contained in:
parent
143b45999a
commit
8ccd91a459
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
**/node_modules/**
|
||||
12
flake.lock
generated
12
flake.lock
generated
@ -98,11 +98,11 @@
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1760878510,
|
||||
"narHash": "sha256-K5Osef2qexezUfs0alLvZ7nQFTGS9DL2oTVsIXsqLgs=",
|
||||
"lastModified": 1761373498,
|
||||
"narHash": "sha256-Q/uhWNvd7V7k1H1ZPMy/vkx3F8C13ZcdrKjO7Jv7v0c=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5e2a59a5b1a82f89f2c7e598302a9cacebb72a67",
|
||||
"rev": "6a08e6bb4e46ff7fcbb53d409b253f6bad8a28ce",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -114,11 +114,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1761016216,
|
||||
"narHash": "sha256-G/iC4t/9j/52i/nm+0/4ybBmAF4hzR8CNHC75qEhjHo=",
|
||||
"lastModified": 1761468971,
|
||||
"narHash": "sha256-vY2OLVg5ZTobdroQKQQSipSIkHlxOTrIF1fsMzPh8w8=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "481cf557888e05d3128a76f14c76397b7d7cc869",
|
||||
"rev": "78e34d1667d32d8a0ffc3eba4591ff256e80576e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@ -345,6 +345,7 @@
|
||||
"waybar".source = config.lib.file.mkOutOfStoreSymlink "/home/nate/nixos/nate-work/linked-dotfiles/waybar";
|
||||
# Shared
|
||||
"helix".source = config.lib.file.mkOutOfStoreSymlink "/home/nate/nixos/shared/linked-dotfiles/helix";
|
||||
"opencode".source = config.lib.file.mkOutOfStoreSymlink "/home/nate/nixos/shared/linked-dotfiles/opencode";
|
||||
|
||||
# Theme files
|
||||
"gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Catppuccin Macchiato Minimal - Judicious Syntax Highlighting
|
||||
# Uses only 4 colors for syntax: lavender (keywords), green (strings), peach (numbers), mauve (comments)
|
||||
# Uses only 4 colors for syntax
|
||||
# Functions and variables remain plain text for reduced visual noise
|
||||
|
||||
"ui.background" = { bg = "base" }
|
||||
@ -98,7 +98,7 @@
|
||||
"variable.parameter" = "text"
|
||||
"variable.other.member" = "text"
|
||||
|
||||
"type" = "lavender" # Types are slightly highlighted
|
||||
"type" = { fg = "lavender", modifiers = ["italic"]} # Types are slightly highlighted
|
||||
"type.builtin" = "lavender"
|
||||
|
||||
"constructor" = "text" # Constructors are plain text
|
||||
|
||||
59
shared/linked-dotfiles/opencode/agent/pr-reviewer.md
Normal file
59
shared/linked-dotfiles/opencode/agent/pr-reviewer.md
Normal file
@ -0,0 +1,59 @@
|
||||
---
|
||||
description: Reviews pull requests to verify work is ready for team review - runs comprehensive validation checks and provides approval or feedback
|
||||
mode: subagent
|
||||
model: anthropic/claude-sonnet-4-5
|
||||
temperature: 0.1
|
||||
tools:
|
||||
write: false
|
||||
edit: false
|
||||
bash: true
|
||||
permission:
|
||||
bash:
|
||||
"make *": allow
|
||||
"gh pr *": allow
|
||||
"rg *": allow
|
||||
"test *": allow
|
||||
"grep *": allow
|
||||
"*": ask
|
||||
---
|
||||
|
||||
You are a pull request reviewer. Your job is to verify that work is ready for human code review.
|
||||
|
||||
## Your Process
|
||||
|
||||
1. **Verify the work is ready for review**
|
||||
- Check that the PR exists and is accessible
|
||||
- Confirm changes are committed and pushed
|
||||
- Ensure PR description is complete
|
||||
|
||||
2. **Use the go-pr-review skill**
|
||||
- Invoke the `go-pr-review` skill to perform comprehensive validation
|
||||
- The skill will check repository compatibility, run tests, validate code quality
|
||||
- Trust the skill's validation results
|
||||
|
||||
3. **Provide your conclusion**
|
||||
- If go-pr-review finds critical issues: Report "Needs work" with specific issues to fix
|
||||
- If go-pr-review approves or has only minor suggestions: Report "Ready for review"
|
||||
- Always include a brief summary of what was validated
|
||||
|
||||
## Important Guidelines
|
||||
|
||||
- Be thorough but efficient - rely on the go-pr-review skill for detailed checks
|
||||
- Never modify code - you're reviewing only
|
||||
- Provide actionable feedback if issues are found
|
||||
- Be clear about whether work can proceed to human review or needs fixes first
|
||||
|
||||
## Response Format
|
||||
|
||||
Conclude your review with one of:
|
||||
|
||||
**✅ Ready for review**
|
||||
- All validations passed
|
||||
- Code quality meets standards
|
||||
- Tests are passing
|
||||
- Ready for human code review
|
||||
|
||||
**❌ Needs work**
|
||||
- [List critical issues that must be fixed]
|
||||
- [Provide specific guidance on what to address]
|
||||
- Re-review after fixes are applied
|
||||
17
shared/linked-dotfiles/opencode/bun.lock
Normal file
17
shared/linked-dotfiles/opencode/bun.lock
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@opencode-ai/plugin": "0.15.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@opencode-ai/plugin": ["@opencode-ai/plugin@0.15.2", "", { "dependencies": { "@opencode-ai/sdk": "0.15.2", "zod": "4.1.8" } }, "sha512-cCttqxDou+OPQzjc20cB4xxuSMMSowZMpvlioIgyzyhp8B7Gc5hh1kY796nly7vjaQfUcLg8pOmRJSLrbxj98g=="],
|
||||
|
||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@0.15.2", "", {}, "sha512-m2aU0TiZj7/o1JvYmoqF7ichrKZcWi4UTx3WYlDXpRJvfZX0gnLKLJAlTKfHkisytGlrlgmST2kt/YQrAjc0wQ=="],
|
||||
|
||||
"zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="],
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,25 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
// Theme configuration
|
||||
"theme": "catppuccin",
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"autoupdate": false,
|
||||
"plugin": [
|
||||
// "skills"
|
||||
// "swaync-notifications"
|
||||
]
|
||||
"plugin": [], // local plugins do not need to be added here
|
||||
"agent": {
|
||||
// "pr-reviewer": {
|
||||
// "description": "Reviews pull requests to verify work is ready for team review",
|
||||
// "mode": "subagent",
|
||||
// }
|
||||
},
|
||||
"mcp": {
|
||||
"atlassian-mcp-server": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"mcp-remote",
|
||||
"https://mcp.atlassian.com/v1/sse"
|
||||
],
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
6
shared/linked-dotfiles/opencode/package.json
Normal file
6
shared/linked-dotfiles/opencode/package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@opencode-ai/plugin": "0.15.2",
|
||||
"gray-matter": "^4.0.3"
|
||||
}
|
||||
}
|
||||
340
shared/linked-dotfiles/opencode/skills/do-job/SKILL.md
Normal file
340
shared/linked-dotfiles/opencode/skills/do-job/SKILL.md
Normal file
@ -0,0 +1,340 @@
|
||||
---
|
||||
name: do-job
|
||||
description: Use when starting work on Jira tickets - fetches To Do tickets, creates git worktrees with proper PI-XXXXX naming, implements features using TDD (test-first), commits with ticket references, creates draft PRs, validates work with PR review, and transitions tickets through workflow to Testing
|
||||
---
|
||||
|
||||
# Do Job
|
||||
|
||||
Complete developer workflow from ticket selection to validated draft PR using TDD and git worktrees.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use when:
|
||||
- Starting work on a new Jira ticket
|
||||
- Need to set up development environment for ticket work
|
||||
- Implementing features using test-driven development
|
||||
- Creating PRs for Jira-tracked work
|
||||
|
||||
## Workflow Checklist
|
||||
|
||||
Copy and track progress:
|
||||
|
||||
```
|
||||
Ticket Workflow Progress:
|
||||
- [ ] Step 1: Fetch and select To Do ticket
|
||||
- [ ] Step 2: Move ticket to In Progress
|
||||
- [ ] Step 3: Set up git worktree
|
||||
- [ ] Step 4: Write failing tests (TDD)
|
||||
- [ ] Step 5: Implement feature/fix
|
||||
- [ ] Step 6: Verify tests pass
|
||||
- [ ] Step 7: Commit with PI-XXXXX reference
|
||||
- [ ] Step 8: Push branch
|
||||
- [ ] Step 9: Create draft PR
|
||||
- [ ] Step 10: Review work with PR reviewer
|
||||
- [ ] Step 11: Link PR to ticket
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Verify environment:
|
||||
|
||||
```bash
|
||||
# Check Jira access
|
||||
atlassian-mcp-server_getAccessibleAtlassianResources
|
||||
|
||||
# Check GitHub CLI
|
||||
gh auth status
|
||||
|
||||
# Verify in repos root directory
|
||||
ls -d */
|
||||
```
|
||||
|
||||
## Step 1: Fetch and Select Ticket
|
||||
|
||||
```bash
|
||||
# Get To Do tickets
|
||||
atlassian-mcp-server_searchJiraIssuesUsingJql \
|
||||
cloudId="<cloud-id>" \
|
||||
jql="assignee = currentUser() AND status = 'To Do' ORDER BY priority DESC, updated DESC" \
|
||||
fields='["summary", "description", "status", "priority"]'
|
||||
```
|
||||
|
||||
Review tickets and select one based on priority and description.
|
||||
|
||||
## Step 2: Move Ticket to In Progress
|
||||
|
||||
```bash
|
||||
atlassian-mcp-server_transitionJiraIssue \
|
||||
cloudId="<cloud-id>" \
|
||||
issueIdOrKey="PI-XXXXX" \
|
||||
transition='{"id": "41"}' # In Progress transition ID
|
||||
```
|
||||
|
||||
Add comment explaining work start:
|
||||
|
||||
```bash
|
||||
atlassian-mcp-server_addCommentToJiraIssue \
|
||||
cloudId="<cloud-id>" \
|
||||
issueIdOrKey="PI-XXXXX" \
|
||||
commentBody="Starting work on this ticket using TDD approach"
|
||||
```
|
||||
|
||||
## Step 3: Set Up Git Worktree
|
||||
|
||||
**CRITICAL: All branches and commits MUST include PI-XXXXX ticket number**
|
||||
|
||||
### Identify Repository
|
||||
|
||||
From repos root directory, determine which repo based on ticket description and summary.
|
||||
|
||||
### Create Worktree
|
||||
|
||||
```bash
|
||||
# Navigate to develop branch of target repo
|
||||
cd <repo-name>/develop
|
||||
|
||||
# Pull latest changes
|
||||
git pull
|
||||
|
||||
# Create worktree with proper naming
|
||||
# Pattern: ../<descriptive-name> with branch nate/PI-XXXXX_descriptive-name
|
||||
git worktree add ../<descriptive-name> -b nate/PI-XXXXX_descriptive-name
|
||||
|
||||
# Navigate to new worktree
|
||||
cd ../<descriptive-name>
|
||||
```
|
||||
|
||||
**Naming conventions:**
|
||||
- Directory: Short descriptive name (e.g., `rename-folder-fix`)
|
||||
- Branch: `nate/PI-XXXXX_descriptive-name` (e.g., `nate/PI-70535_rename-folder-fix`)
|
||||
- **MUST include PI-XXXXX** in branch name
|
||||
|
||||
## Step 4: Build Implementation Plan
|
||||
|
||||
Analyze ticket requirements and create TDD plan:
|
||||
|
||||
1. **Understand requirements** from ticket description
|
||||
2. **Identify affected code** areas
|
||||
3. **Plan test cases** covering:
|
||||
- Happy path
|
||||
- Edge cases
|
||||
- Error conditions
|
||||
4. **Plan implementation** approach
|
||||
|
||||
## Step 5: TDD Implementation
|
||||
|
||||
### Write Failing Tests First
|
||||
|
||||
**CRITICAL: Write tests BEFORE implementation**
|
||||
|
||||
```bash
|
||||
# Identify test framework from repo
|
||||
ls *_test.* test/ tests/ __tests__/
|
||||
|
||||
# Create or modify test file
|
||||
# Write test that validates missing functionality
|
||||
```
|
||||
|
||||
Test should:
|
||||
- Clearly describe expected behavior
|
||||
- Cover the specific bug/feature from ticket
|
||||
- **Fail initially** (validates test is working)
|
||||
|
||||
### Run Failing Tests
|
||||
|
||||
```bash
|
||||
# Verify test fails (proves test is valid)
|
||||
<run-test-command>
|
||||
```
|
||||
|
||||
Expected: Test fails with clear error showing missing functionality.
|
||||
|
||||
### Implement Feature/Fix
|
||||
|
||||
Write minimal code to make test pass:
|
||||
|
||||
```bash
|
||||
# Implement the feature or fix
|
||||
# Focus on making test pass, not perfection
|
||||
```
|
||||
|
||||
### Run Tests Again
|
||||
|
||||
```bash
|
||||
# Verify test now passes
|
||||
<run-test-command>
|
||||
```
|
||||
|
||||
Expected: All tests pass.
|
||||
|
||||
### Refactor (if needed)
|
||||
|
||||
Clean up implementation while keeping tests passing:
|
||||
|
||||
- Improve code clarity
|
||||
- Remove duplication
|
||||
- Follow project conventions
|
||||
- **Keep tests passing**
|
||||
|
||||
## Step 6: Verify Complete Solution
|
||||
|
||||
```bash
|
||||
# Run full test suite
|
||||
<full-test-command>
|
||||
|
||||
# Run linting (if available)
|
||||
<lint-command>
|
||||
|
||||
# Run type checking (if available)
|
||||
<typecheck-command>
|
||||
```
|
||||
|
||||
All checks must pass before proceeding.
|
||||
|
||||
## Step 7: Commit Changes
|
||||
|
||||
**CRITICAL: Commit message MUST include PI-XXXXX**
|
||||
|
||||
```bash
|
||||
# Stage changes
|
||||
git add .
|
||||
|
||||
# Commit with ticket reference
|
||||
git commit -m "PI-XXXXX: <concise description>
|
||||
|
||||
<detailed explanation of changes>
|
||||
- What was changed
|
||||
- Why it was changed
|
||||
- How it addresses the ticket"
|
||||
```
|
||||
|
||||
**Commit message format:**
|
||||
- First line: `PI-XXXXX: <summary>` (50 chars max)
|
||||
- Blank line
|
||||
- Detailed description explaining the why and how
|
||||
- Reference ticket number (PI-XXXXX) in first line
|
||||
|
||||
## Step 8: Push Branch
|
||||
|
||||
```bash
|
||||
# Push to remote
|
||||
git push -u origin nate/PI-XXXXX_descriptive-name
|
||||
```
|
||||
|
||||
## Step 9: Create Draft PR
|
||||
|
||||
```bash
|
||||
# Create draft PR with gh CLI
|
||||
gh pr create \
|
||||
--draft \
|
||||
--title "PI-XXXXX: <descriptive title>" \
|
||||
--body "$(cat <<'PRBODY'
|
||||
## Summary
|
||||
- Fixes issue described in PI-XXXXX
|
||||
- Implements <feature/fix> using TDD approach
|
||||
|
||||
## Changes
|
||||
- Added tests for <functionality>
|
||||
- Implemented <feature/fix>
|
||||
- Verified all tests pass
|
||||
|
||||
## Testing
|
||||
- [x] Unit tests added and passing
|
||||
- [x] Linting passes
|
||||
- [x] Manual testing completed
|
||||
|
||||
## Jira
|
||||
Related ticket: PI-XXXXX
|
||||
|
||||
## Notes
|
||||
Ready for review. Once approved, will move ticket to Pull Request status.
|
||||
PRBODY
|
||||
)"
|
||||
```
|
||||
|
||||
**Save PR URL** returned by command for next steps.
|
||||
|
||||
## Step 10: Review Work with PR Reviewer
|
||||
|
||||
**CRITICAL: Invoke @pr-reviewer subagent to validate work before linking to ticket**
|
||||
|
||||
```bash
|
||||
# Invoke the pr-reviewer subagent
|
||||
@pr-reviewer please review the PR I just created
|
||||
```
|
||||
|
||||
The pr-reviewer will:
|
||||
- Verify the repository is compatible (Go with Makefile)
|
||||
- Run all validation commands (tests, linting, type checking)
|
||||
- Review code quality against project standards
|
||||
- Check for security issues and best practices
|
||||
- Provide verdict: Ready for review OR needs work
|
||||
|
||||
**If pr-reviewer finds issues:**
|
||||
1. Address the critical issues identified
|
||||
2. Re-run tests and validations
|
||||
3. Commit fixes with `PI-XXXXX: Address PR review feedback`
|
||||
4. Push updates
|
||||
5. Invoke @pr-reviewer again to re-validate
|
||||
|
||||
**Only proceed to Step 11 when pr-reviewer gives approval.**
|
||||
|
||||
## Step 11: Link PR to Ticket
|
||||
|
||||
```bash
|
||||
# Add PR link to Jira ticket
|
||||
atlassian-mcp-server_addCommentToJiraIssue \
|
||||
cloudId="<cloud-id>" \
|
||||
issueIdOrKey="PI-XXXXX" \
|
||||
commentBody="Draft PR created: <pr-url>
|
||||
|
||||
Implementation complete using TDD approach. Ready for code review."
|
||||
```
|
||||
|
||||
## Post-Workflow Steps (Manual)
|
||||
|
||||
**After automated pr-reviewer approval and manual developer review:**
|
||||
|
||||
1. Remove draft status from PR
|
||||
2. Request code review from team
|
||||
3. Address any additional review comments
|
||||
4. Get approval
|
||||
5. **Manual:** Transition ticket to "Pull Request" status (transition ID: 381)
|
||||
6. **Manual:** After merge, SDET moves to "Testing (Service Stack)" (transition ID: 201)
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### Branch Naming
|
||||
- ❌ `fix-bug` (missing ticket number)
|
||||
- ❌ `PI70535-fix` (missing hyphen, no username)
|
||||
- ✅ `nate/PI-70535_rename-folder-fix`
|
||||
|
||||
### Commit Messages
|
||||
- ❌ `fixed bug` (no ticket reference)
|
||||
- ❌ `Updated code for PI-70535` (vague)
|
||||
- ✅ `PI-70535: Fix shared folder rename permission check`
|
||||
|
||||
### TDD Order
|
||||
- ❌ Write code first, then tests
|
||||
- ❌ Skip tests entirely
|
||||
- ✅ Write failing test → Implement → Verify passing → Refactor
|
||||
|
||||
### Worktree Location
|
||||
- ❌ `git worktree add ./feature` (wrong location)
|
||||
- ❌ `git worktree add ~/feature` (absolute path)
|
||||
- ✅ `git worktree add ../feature-name` (parallel to develop)
|
||||
|
||||
## Jira Transition IDs
|
||||
|
||||
Reference for manual transitions:
|
||||
|
||||
- To Do: 11
|
||||
- In Progress: 41
|
||||
- Pull Request: 381
|
||||
- Testing (Service Stack): 201
|
||||
- Done: (varies by project)
|
||||
|
||||
## Reference Materials
|
||||
|
||||
See references/tdd-workflow.md for detailed TDD best practices.
|
||||
See references/git-worktree.md for git worktree patterns and troubleshooting.
|
||||
@ -0,0 +1,236 @@
|
||||
# Git Worktree Patterns
|
||||
|
||||
## Overview
|
||||
|
||||
Git worktrees allow multiple working directories from single repository, enabling parallel work on different branches without stashing or switching.
|
||||
|
||||
## Basic Commands
|
||||
|
||||
### Create Worktree
|
||||
|
||||
```bash
|
||||
# From main/develop branch
|
||||
cd <repo>/develop
|
||||
git pull
|
||||
|
||||
# Create new worktree
|
||||
git worktree add <path> -b <branch-name>
|
||||
```
|
||||
|
||||
### List Worktrees
|
||||
|
||||
```bash
|
||||
git worktree list
|
||||
```
|
||||
|
||||
### Remove Worktree
|
||||
|
||||
```bash
|
||||
# From any location in repo
|
||||
git worktree remove <path>
|
||||
|
||||
# Or manually
|
||||
rm -rf <path>
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
## Naming Patterns
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
repos/
|
||||
├── document-api/
|
||||
│ ├── develop/ # Main worktree
|
||||
│ ├── fix-permissions/ # Feature worktree
|
||||
│ └── add-tags/ # Another feature worktree
|
||||
```
|
||||
|
||||
### Branch Naming
|
||||
|
||||
Format: `<username>/PI-XXXXX_<description>`
|
||||
|
||||
Examples:
|
||||
- `nate/PI-70535_rename-folder-fix`
|
||||
- `nate/PI-70361_upload-permissions`
|
||||
- `nate/PI-69924_delete-access-level`
|
||||
|
||||
## Workflow Patterns
|
||||
|
||||
### Starting Work
|
||||
|
||||
```bash
|
||||
# Navigate to develop
|
||||
cd document-api/develop
|
||||
|
||||
# Update develop
|
||||
git pull
|
||||
|
||||
# Create worktree for ticket
|
||||
git worktree add ../pi-70535-rename-fix -b nate/PI-70535_rename-folder-fix
|
||||
|
||||
# Move to worktree
|
||||
cd ../pi-70535-rename-fix
|
||||
```
|
||||
|
||||
### During Work
|
||||
|
||||
```bash
|
||||
# Normal git operations work in worktree
|
||||
git status
|
||||
git add .
|
||||
git commit -m "PI-70535: Fix folder rename permissions"
|
||||
git push -u origin nate/PI-70535_rename-folder-fix
|
||||
```
|
||||
|
||||
### After PR Merge
|
||||
|
||||
```bash
|
||||
# From anywhere in repo
|
||||
git worktree remove ../pi-70535-rename-fix
|
||||
|
||||
# Clean up
|
||||
git worktree prune
|
||||
git branch -d nate/PI-70535_rename-folder-fix
|
||||
|
||||
# Update develop
|
||||
cd develop
|
||||
git pull
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Worktree Already Exists
|
||||
|
||||
```bash
|
||||
# Error: worktree already exists
|
||||
# Solution: Remove old worktree first
|
||||
git worktree remove <path>
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
### Branch Already Exists
|
||||
|
||||
```bash
|
||||
# Error: branch already exists
|
||||
# Solution: Use existing branch or delete old one
|
||||
git worktree add <path> <existing-branch>
|
||||
|
||||
# Or delete old branch
|
||||
git branch -D <branch-name>
|
||||
git worktree add <path> -b <branch-name>
|
||||
```
|
||||
|
||||
### Locked Worktree
|
||||
|
||||
```bash
|
||||
# If worktree shows as locked
|
||||
git worktree unlock <path>
|
||||
git worktree remove <path>
|
||||
```
|
||||
|
||||
### Orphaned Worktrees
|
||||
|
||||
```bash
|
||||
# Clean up references to deleted worktrees
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Keep Worktrees Short-Lived
|
||||
|
||||
- Create for specific ticket
|
||||
- Remove after PR merged
|
||||
- Don't accumulate many worktrees
|
||||
|
||||
### Use Descriptive Names
|
||||
|
||||
```bash
|
||||
# ❌ Bad
|
||||
git worktree add ../work -b fix
|
||||
|
||||
# ✅ Good
|
||||
git worktree add ../rename-folder-fix -b nate/PI-70535_rename-folder-fix
|
||||
```
|
||||
|
||||
### Always Branch from Latest
|
||||
|
||||
```bash
|
||||
# Update base branch before creating worktree
|
||||
cd develop
|
||||
git pull
|
||||
git worktree add ../feature -b username/PI-XXXXX_feature
|
||||
```
|
||||
|
||||
### Clean Up Regularly
|
||||
|
||||
```bash
|
||||
# List all worktrees
|
||||
git worktree list
|
||||
|
||||
# Remove merged/abandoned worktrees
|
||||
git worktree remove <path>
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
## Advantages Over Branch Switching
|
||||
|
||||
### Parallel Work
|
||||
|
||||
Work on multiple tickets simultaneously without switching contexts:
|
||||
|
||||
```
|
||||
Terminal 1: cd document-api/develop # Review PRs
|
||||
Terminal 2: cd document-api/feature-1 # Active development
|
||||
Terminal 3: cd document-api/hotfix # Emergency fix
|
||||
```
|
||||
|
||||
### Preserve State
|
||||
|
||||
Each worktree maintains its own:
|
||||
- Working directory state
|
||||
- Staged changes
|
||||
- Build artifacts
|
||||
- IDE configuration
|
||||
|
||||
### Avoid Stashing
|
||||
|
||||
No need to stash changes when switching tasks:
|
||||
|
||||
```bash
|
||||
# Traditional flow (with stashing)
|
||||
git stash
|
||||
git checkout other-branch
|
||||
# ... do work ...
|
||||
git checkout original-branch
|
||||
git stash pop
|
||||
|
||||
# Worktree flow (no stashing)
|
||||
cd ../other-worktree
|
||||
# ... do work ...
|
||||
cd ../original-worktree
|
||||
# Everything still there
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
### Shared References
|
||||
|
||||
All worktrees share:
|
||||
- Git objects
|
||||
- Remote configuration
|
||||
- Git hooks
|
||||
- Submodules
|
||||
|
||||
### Disk Space
|
||||
|
||||
Each worktree requires full working directory (but shares `.git` objects).
|
||||
|
||||
### Cannot Checkout Same Branch
|
||||
|
||||
```bash
|
||||
# Error: branch already checked out
|
||||
# One branch can only be checked out in one worktree at a time
|
||||
git worktree add ../dup -b existing-branch # Fails if already checked out
|
||||
```
|
||||
@ -0,0 +1,173 @@
|
||||
# Test-Driven Development Workflow
|
||||
|
||||
## Core TDD Cycle
|
||||
|
||||
1. **Red** - Write failing test
|
||||
2. **Green** - Make test pass
|
||||
3. **Refactor** - Improve code while keeping tests passing
|
||||
|
||||
## Writing Effective Tests
|
||||
|
||||
### Test Structure
|
||||
|
||||
```
|
||||
# Arrange - Set up test data and conditions
|
||||
# Act - Execute the code being tested
|
||||
# Assert - Verify expected behavior
|
||||
```
|
||||
|
||||
### Good Test Characteristics
|
||||
|
||||
- **Isolated** - Tests don't depend on each other
|
||||
- **Repeatable** - Same input always produces same output
|
||||
- **Fast** - Tests run quickly
|
||||
- **Clear** - Test name describes what's being tested
|
||||
- **Focused** - One concept per test
|
||||
|
||||
### Test Naming
|
||||
|
||||
```
|
||||
test_<function>_<scenario>_<expected_result>
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `test_rename_folder_as_owner_succeeds`
|
||||
- `test_rename_folder_without_permission_returns_403`
|
||||
- `test_rename_folder_with_empty_name_returns_400`
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Testing Error Conditions
|
||||
|
||||
```javascript
|
||||
// Test expected errors
|
||||
test('rename_folder_without_permission_returns_403', async () => {
|
||||
// Arrange: Set up user without permissions
|
||||
const user = createUserWithoutPermissions();
|
||||
|
||||
// Act: Attempt rename
|
||||
const response = await renameFolder(user, folderId, newName);
|
||||
|
||||
// Assert: Verify 403 error
|
||||
expect(response.status).toBe(403);
|
||||
expect(response.error).toContain('forbidden');
|
||||
});
|
||||
```
|
||||
|
||||
### Testing Happy Path
|
||||
|
||||
```javascript
|
||||
test('rename_folder_as_owner_succeeds', async () => {
|
||||
// Arrange: Set up folder with owner
|
||||
const owner = createOwner();
|
||||
const folder = createFolder(owner);
|
||||
|
||||
// Act: Rename folder
|
||||
const response = await renameFolder(owner, folder.id, 'NewName');
|
||||
|
||||
// Assert: Verify success
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.data.name).toBe('NewName');
|
||||
});
|
||||
```
|
||||
|
||||
### Testing Edge Cases
|
||||
|
||||
```javascript
|
||||
test('rename_folder_with_special_characters_sanitizes_name', async () => {
|
||||
const owner = createOwner();
|
||||
const folder = createFolder(owner);
|
||||
|
||||
const response = await renameFolder(owner, folder.id, '<script>alert(1)</script>');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.data.name).not.toContain('<script>');
|
||||
});
|
||||
```
|
||||
|
||||
## TDD Best Practices
|
||||
|
||||
### Start Simple
|
||||
|
||||
Write simplest test first, then add complexity:
|
||||
|
||||
1. Happy path with minimal data
|
||||
2. Add edge cases
|
||||
3. Add error conditions
|
||||
4. Add integration scenarios
|
||||
|
||||
### One Test at a Time
|
||||
|
||||
- Write one test
|
||||
- Watch it fail
|
||||
- Make it pass
|
||||
- Refactor if needed
|
||||
- Repeat
|
||||
|
||||
### Keep Tests Independent
|
||||
|
||||
```javascript
|
||||
// ❌ Bad - Tests depend on order
|
||||
test('create_folder', () => { /* creates folder with id=1 */ });
|
||||
test('rename_folder', () => { /* assumes folder id=1 exists */ });
|
||||
|
||||
// ✅ Good - Each test sets up own data
|
||||
test('create_folder', () => {
|
||||
const folder = createFolder();
|
||||
expect(folder.id).toBeDefined();
|
||||
});
|
||||
|
||||
test('rename_folder', () => {
|
||||
const folder = createFolder(); // Own setup
|
||||
const result = renameFolder(folder.id, 'NewName');
|
||||
expect(result.name).toBe('NewName');
|
||||
});
|
||||
```
|
||||
|
||||
### Test Behavior, Not Implementation
|
||||
|
||||
```javascript
|
||||
// ❌ Bad - Tests internal implementation
|
||||
test('uses_postgres_query', () => {
|
||||
expect(mockDb.query).toHaveBeenCalledWith('UPDATE folders...');
|
||||
});
|
||||
|
||||
// ✅ Good - Tests behavior
|
||||
test('rename_updates_folder_name', () => {
|
||||
renameFolder(folderId, 'NewName');
|
||||
const folder = getFolder(folderId);
|
||||
expect(folder.name).toBe('NewName');
|
||||
});
|
||||
```
|
||||
|
||||
## When to Refactor
|
||||
|
||||
Refactor when tests are green and you notice:
|
||||
|
||||
- Duplication
|
||||
- Long functions
|
||||
- Unclear variable names
|
||||
- Complex conditionals
|
||||
- Hard-coded values
|
||||
|
||||
**Always keep tests passing during refactoring**
|
||||
|
||||
## Handling Legacy Code
|
||||
|
||||
When adding tests to existing code without tests:
|
||||
|
||||
1. Write characterization tests (document current behavior)
|
||||
2. Refactor to make code testable
|
||||
3. Add tests for new functionality
|
||||
4. Gradually improve test coverage
|
||||
|
||||
## Test Coverage
|
||||
|
||||
Aim for coverage of:
|
||||
|
||||
- All new code paths
|
||||
- Bug fixes (test the bug scenario)
|
||||
- Edge cases
|
||||
- Error conditions
|
||||
|
||||
Not aiming for 100% - focus on meaningful coverage.
|
||||
Loading…
Reference in New Issue
Block a user