-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat(hooks): add support for custom hooks #345
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
amondnet
wants to merge
18
commits into
github:main
Choose a base branch
from
amondnet:feat-hooks
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+542
β71
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
7fdfc50
feat(hooks): add support for custom hooks
amondnet 96d9e15
Update hooks/post-checkout.ps1.sample
amondnet c4c1027
Update hooks/post-checkout.sample
amondnet c9080da
Update src/specify_cli/__init__.py
amondnet 1ffd2ca
feat: add validation for feature number in create-new-feature scripts
amondnet b0b8a91
feat(hooks): update post-checkout and post-specify hooks to accept adβ¦
amondnet 02d0915
Update templates/commands/specify.md
amondnet b469525
feat(hooks): enhance script handling with dynamic extensions and seleβ¦
amondnet 795f0e2
refactor: require feature number as a parameter in create-new-featureβ¦
amondnet 0933175
refactor: add shebang check for scripts and hooks in ensure_executablβ¦
amondnet a9643c0
Update src/specify_cli/__init__.py
amondnet 43c4d70
Update templates/commands/specify.md
amondnet 8b8788a
refactor(hooks): add hook skipping logic for permission updates
amondnet ffaed31
refactor(hooks): extract hook extension logic into a separate function
amondnet 25b69a7
Update src/specify_cli/__init__.py
amondnet d53641e
Update scripts/bash/create-new-feature.sh
amondnet 63082e7
Update src/specify_cli/__init__.py
amondnet b729f9c
docs: update README with hook argument details
amondnet File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
# Specify Hooks | ||
|
||
This directory contains Git-style hook script samples that customize the `/specify` command workflow. All hooks are optional and follow Git's naming conventions for familiar, intuitive usage. | ||
|
||
## Hook Activation | ||
|
||
Hooks are provided as `.sample` files and must be activated by removing the `.sample` extension: | ||
|
||
**Unix/Linux/macOS:** | ||
```bash | ||
# Activate bash hook (example: prepare-feature-num) | ||
cp .specify/hooks/prepare-feature-num.sample .specify/hooks/prepare-feature-num | ||
chmod +x .specify/hooks/prepare-feature-num | ||
``` | ||
|
||
**Windows PowerShell:** | ||
```powershell | ||
# Activate PowerShell hook | ||
Copy-Item .specify/hooks/prepare-feature-num.ps1.sample .specify/hooks/prepare-feature-num.ps1 | ||
``` | ||
|
||
**Cross-platform support:** The system automatically detects and uses the appropriate hook format (`.ps1` for Windows, executable scripts for Unix). | ||
|
||
## Available Hooks (Git-Style Naming) | ||
|
||
### `pre-specify` - Pre-processing Hook | ||
- **When**: Before the entire specify workflow begins | ||
- **Purpose**: Validation, setup, or preprocessing tasks | ||
- **Arguments**: `$1` = feature description | ||
- **Exit codes**: Non-zero exit codes show warnings but don't stop execution | ||
|
||
**Example uses:** | ||
- Validate feature description format and length | ||
- Check prerequisites or dependencies | ||
- Set up external resources or authenticate | ||
|
||
### `prepare-feature-num` - Feature Number Preparation Hook | ||
- **When**: Before auto-incrementing feature number (similar to Git's `prepare-commit-msg`) | ||
- **Purpose**: Provide custom feature numbering from external sources | ||
- **Arguments**: `$1` = feature description | ||
- **Output**: Integer feature number (stdout) | ||
- **Fallback**: If hook fails or outputs nothing, auto-increment is used | ||
|
||
**Example uses:** | ||
- Fetch feature number from external spec server | ||
- Create GitHub issue and use issue number | ||
- Implement custom numbering schemes | ||
|
||
### `post-checkout` - Post-Checkout Hook | ||
- **When**: After branch creation and checkout (matches Git's `post-checkout`) | ||
- **Purpose**: Setup tasks after branch creation but before spec writing | ||
- **Arguments**: | ||
- `$1` = feature description | ||
- `$2` = feature number | ||
- `$3` = branch name | ||
- `$4` = spec file path | ||
- **Environment**: `BRANCH_NAME`, `SPEC_FILE`, `FEATURE_NUM` also available | ||
- **Exit codes**: Non-zero exit codes show warnings but don't stop execution | ||
|
||
**Example uses:** | ||
- Initialize additional project files | ||
- Set up branch-specific configurations | ||
- Create directory structures | ||
- Send branch creation notifications | ||
|
||
### `post-specify` - Post-Specification Hook | ||
- **When**: After spec file is completely written (true post-specify) | ||
- **Purpose**: Final integration tasks and notifications | ||
- **Arguments**: | ||
- `$1` = feature description | ||
- `$2` = feature number | ||
- `$3` = branch name | ||
- `$4` = spec file path | ||
- **Environment**: `BRANCH_NAME`, `SPEC_FILE`, `FEATURE_NUM` also available | ||
- **Exit codes**: Non-zero exit codes show warnings but don't stop execution | ||
|
||
**Example uses:** | ||
- Create GitHub issues linking to completed specs | ||
- Send completion notifications | ||
- Trigger CI/CD pipelines for spec review | ||
- Update external tracking systems | ||
|
||
## Hook Examples | ||
|
||
### Custom Feature Numbering from Server | ||
|
||
**Bash version:** | ||
```bash | ||
#!/bin/bash | ||
# .specify/hooks/prepare-feature-num | ||
FEATURE_DESC="$1" | ||
FEATURE_NUMBER=$(curl -s "$SPEC_SERVER/api/next-number") | ||
echo "$FEATURE_NUMBER" | ||
``` | ||
|
||
**PowerShell version:** | ||
```powershell | ||
#!/usr/bin/env pwsh | ||
# .specify/hooks/prepare-feature-num.ps1 | ||
param([string]$FeatureDescription) | ||
$featureNumber = Invoke-RestMethod -Uri "$env:SPEC_SERVER/api/next-number" | ||
Write-Output $featureNumber | ||
``` | ||
|
||
### GitHub Issue for Feature Number | ||
|
||
**Bash version:** | ||
```bash | ||
#!/bin/bash | ||
# .specify/hooks/prepare-feature-num | ||
FEATURE_DESC="$1" | ||
ISSUE_URL=$(gh issue create --title "Spec: $FEATURE_DESC" --body "Specification development") | ||
ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -o '[0-9]*$') | ||
echo "$ISSUE_NUMBER" | ||
``` | ||
|
||
**PowerShell version:** | ||
```powershell | ||
#!/usr/bin/env pwsh | ||
# .specify/hooks/prepare-feature-num.ps1 | ||
param([string]$FeatureDescription) | ||
$issueUrl = gh issue create --title "Spec: $FeatureDescription" --body "Specification development" | ||
$issueNumber = [regex]::Match($issueUrl, '\d+$').Value | ||
Write-Output $issueNumber | ||
``` | ||
|
||
### Post-Checkout Setup | ||
|
||
**Bash version:** | ||
```bash | ||
#!/bin/bash | ||
# .specify/hooks/post-checkout | ||
FEATURE_DESC="$1" | ||
FEATURE_NUM="$2" | ||
BRANCH_NAME="$3" | ||
SPEC_FILE="$4" | ||
# Create additional project directories | ||
mkdir -p "docs/$BRANCH_NAME" | ||
# Set up branch-specific configuration | ||
echo "Branch $BRANCH_NAME (#$FEATURE_NUM) created for: $FEATURE_DESC" > "docs/$BRANCH_NAME/info.txt" | ||
``` | ||
|
||
### Post-Specification Notification | ||
|
||
**Bash version:** | ||
```bash | ||
#!/bin/bash | ||
# .specify/hooks/post-specify | ||
FEATURE_DESC="$1" | ||
FEATURE_NUM="$2" | ||
BRANCH_NAME="$3" | ||
SPEC_FILE="$4" | ||
# Create completion issue | ||
gh issue create --title "Spec Complete #$FEATURE_NUM: $FEATURE_DESC" --body "Specification ready for review: $SPEC_FILE on branch $BRANCH_NAME" | ||
# Send notification | ||
echo "Specification $FEATURE_NUM completed: $SPEC_FILE" | mail -s "Spec Ready" [email protected] | ||
``` | ||
|
||
## Technical Notes | ||
|
||
### Platform-Specific Behavior | ||
- **Unix/Linux/macOS**: Hooks must be executable (`chmod +x`). System looks for exact hook name. | ||
- **Windows**: PowerShell hooks use `.ps1` extension. No execute permission needed. | ||
- **Cross-platform**: System automatically detects and uses appropriate hook format. | ||
|
||
### Hook Execution | ||
- Hook arguments vary by type: | ||
- `pre-specify` and `prepare-feature-num`: receive only feature description (`$1`) | ||
- `post-checkout` and `post-specify`: receive feature description (`$1`) and have access to environment variables (BRANCH_NAME, SPEC_FILE, FEATURE_NUM) | ||
- The `prepare-feature-num` hook should output only the number to stdout | ||
- Failed hooks generate warnings but don't stop the specification process | ||
- Non-existent or non-executable hook files are safely ignored | ||
|
||
### Available Hook Formats | ||
- `hook-name` - Bash/shell script (Unix/Linux/macOS) | ||
- `hook-name.ps1` - PowerShell script (Windows/cross-platform) | ||
|
||
### Hook Execution Order | ||
1. `pre-specify` - Workflow validation and setup | ||
2. `prepare-feature-num` - Custom feature numbering (optional) | ||
3. **Script execution** - Branch/directory creation | ||
4. `post-checkout` - Post-branch setup tasks | ||
5. **Spec writing** - Template processing and content generation | ||
6. `post-specify` - Completion notifications and final tasks | ||
|
||
## Customization | ||
|
||
**To activate and customize hooks:** | ||
|
||
1. **Copy the sample**: Remove `.sample` from the appropriate hook file | ||
2. **Make executable** (Unix only): `chmod +x .specify/hooks/hook-name` | ||
3. **Edit the hook**: Customize the logic for your needs | ||
4. **Test**: Run the hook manually with test data | ||
|
||
**Example activation:** | ||
```bash | ||
# Unix/Linux/macOS - Activate prepare-feature-num hook | ||
cp .specify/hooks/prepare-feature-num.sample .specify/hooks/prepare-feature-num | ||
chmod +x .specify/hooks/prepare-feature-num | ||
|
||
# Windows PowerShell - Activate prepare-feature-num hook | ||
Copy-Item .specify/hooks/prepare-feature-num.ps1.sample .specify/hooks/prepare-feature-num.ps1 | ||
``` | ||
|
||
The Git-style naming provides familiar patterns for developers already using Git hooks, making the system more intuitive and easier to understand. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env pwsh | ||
# Post-checkout hook: Runs after feature branch and directory creation | ||
# Arguments: $args[0] = feature description | ||
# Environment: $env:BRANCH_NAME, $env:SPEC_FILE, $env:FEATURE_NUM available | ||
|
||
param( | ||
[Parameter(Position=0)] | ||
[string]$FeatureDescription | ||
) | ||
|
||
# Example: Create GitHub issue | ||
# if (Get-Command gh -ErrorAction SilentlyContinue) { | ||
# gh issue create --title "Spec: $FeatureDescription" --body "Branch: $env:BRANCH_NAME, Spec: $env:SPEC_FILE" | ||
# } | ||
|
||
# Example: Send notification | ||
# $message = "Feature $env:FEATURE_NUM created: $env:BRANCH_NAME" | ||
# Send-MailMessage -To "[email protected]" -Subject "New Spec" -Body $message -SmtpServer "smtp.company.com" | ||
|
||
# Default: Do nothing | ||
exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!/bin/bash | ||
# Post-checkout hook: Runs after feature branch and directory creation | ||
# Arguments: $1 = feature description | ||
# Environment: BRANCH_NAME, SPEC_FILE, FEATURE_NUM available | ||
|
||
# Example: Create GitHub issue | ||
# if command -v gh >/dev/null 2>&1; then | ||
# gh issue create --title "Spec: $1" --body "Branch: $BRANCH_NAME, Spec: $SPEC_FILE" | ||
# fi | ||
|
||
# Example: Send notification | ||
# echo "Feature $FEATURE_NUM created: $BRANCH_NAME" | mail -s "New Spec" [email protected] | ||
|
||
# Default: Do nothing | ||
exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#!/usr/bin/env pwsh | ||
# Post-specify hook: Runs after spec file is written and completed | ||
# Arguments: $args[0] = feature description | ||
# Environment: $env:BRANCH_NAME, $env:SPEC_FILE, $env:FEATURE_NUM available | ||
|
||
param( | ||
[Parameter(Position=0)] | ||
[string]$FeatureDescription | ||
) | ||
|
||
# Example: Create GitHub issue linking to completed spec | ||
# if (Get-Command gh -ErrorAction SilentlyContinue) { | ||
# gh issue create --title "Spec Complete: $FeatureDescription" --body "Specification completed: $env:SPEC_FILE on branch $env:BRANCH_NAME" | ||
# } | ||
|
||
# Example: Send completion notification | ||
# $message = "Specification $env:FEATURE_NUM completed: $env:SPEC_FILE" | ||
# Send-MailMessage -To "[email protected]" -Subject "Spec Ready for Review" -Body $message -SmtpServer "smtp.company.com" | ||
|
||
# Example: Trigger CI/CD pipeline | ||
# $body = @{ | ||
# event = "spec_completed" | ||
# branch = $env:BRANCH_NAME | ||
# spec = $env:SPEC_FILE | ||
# } | ConvertTo-Json | ||
# Invoke-RestMethod -Uri $env:CI_WEBHOOK_URL -Method Post -Body $body -ContentType "application/json" | ||
|
||
# Default: Do nothing | ||
exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#!/bin/bash | ||
# Post-specify hook: Runs after spec file is written and completed | ||
# Arguments: $1 = feature description | ||
# Environment: BRANCH_NAME, SPEC_FILE, FEATURE_NUM available | ||
|
||
# Example: Create GitHub issue linking to completed spec | ||
# if command -v gh >/dev/null 2>&1; then | ||
# gh issue create --title "Spec Complete: $1" --body "Specification completed: $SPEC_FILE on branch $BRANCH_NAME" | ||
# fi | ||
|
||
# Example: Send completion notification | ||
# echo "Specification $FEATURE_NUM completed: $SPEC_FILE" | mail -s "Spec Ready for Review" [email protected] | ||
|
||
# Example: Trigger CI/CD pipeline | ||
# curl -X POST "$CI_WEBHOOK_URL" -d '{"event":"spec_completed","branch":"'$BRANCH_NAME'","spec":"'$SPEC_FILE'"}' | ||
|
||
# Default: Do nothing | ||
exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#!/usr/bin/env pwsh | ||
# Pre-specify hook: Runs before feature creation | ||
# Arguments: $args[0] = feature description | ||
# Customize this script to add pre-processing logic | ||
|
||
param( | ||
[Parameter(Position=0)] | ||
[string]$FeatureDescription | ||
) | ||
|
||
# Example: Validate feature description | ||
# if ($FeatureDescription.Length -lt 10) { | ||
# Write-Error "Error: Feature description too short" | ||
# exit 1 | ||
# } | ||
|
||
# Default: Do nothing | ||
exit 0 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.