mirror of
https://github.com/stefanzweifel/git-auto-commit-action.git
synced 2026-01-11 12:08:25 +00:00
WIP Hooks
This commit is contained in:
242
.github/workflows/hook-examples.yml
vendored
Normal file
242
.github/workflows/hook-examples.yml
vendored
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
name: Hook Examples
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Example 1: Use pre_status_hook to unshallow repository
|
||||||
|
unshallow-example:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 1 # Create shallow clone
|
||||||
|
|
||||||
|
- name: Make some changes
|
||||||
|
run: |
|
||||||
|
echo "$(date): Updated by workflow" >> updates.log
|
||||||
|
|
||||||
|
- name: Commit with unshallow hook
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
commit_message: "Update logs with unshallow support"
|
||||||
|
pre_status_hook: |
|
||||||
|
echo "Checking if repository is shallow..."
|
||||||
|
if git rev-parse --is-shallow-repository 2>/dev/null | grep -q true; then
|
||||||
|
echo "Repository is shallow, running git fetch --unshallow"
|
||||||
|
git fetch --unshallow
|
||||||
|
else
|
||||||
|
echo "Repository is not shallow"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Example 2: Use pre_commit_hook for validation
|
||||||
|
validation-example:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '18'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Make changes to JavaScript files
|
||||||
|
run: |
|
||||||
|
echo "console.log('Hello World');" > example.js
|
||||||
|
|
||||||
|
- name: Commit with validation hook
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
commit_message: "Add example JavaScript file"
|
||||||
|
pre_commit_hook: |
|
||||||
|
echo "Running pre-commit validation..."
|
||||||
|
# Validate JavaScript syntax
|
||||||
|
find . -name "*.js" -not -path "./node_modules/*" -exec node -c {} \;
|
||||||
|
echo "JavaScript validation passed!"
|
||||||
|
|
||||||
|
# Run tests if they exist
|
||||||
|
if [ -f "package.json" ] && npm run test --if-present; then
|
||||||
|
echo "Tests passed!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Example 3: Use pre_commit_hook to generate additional files
|
||||||
|
file-generation-example:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Make some changes
|
||||||
|
run: |
|
||||||
|
echo "New feature added" > feature.txt
|
||||||
|
|
||||||
|
- name: Commit with file generation hook
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
commit_message: "Add feature with generated manifest"
|
||||||
|
pre_commit_hook: |
|
||||||
|
echo "Generating build manifest..."
|
||||||
|
|
||||||
|
# Create build info file
|
||||||
|
cat > build-info.json << EOF
|
||||||
|
{
|
||||||
|
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
||||||
|
"commit": "$GITHUB_SHA",
|
||||||
|
"workflow": "$GITHUB_WORKFLOW",
|
||||||
|
"run_id": "$GITHUB_RUN_ID",
|
||||||
|
"actor": "$GITHUB_ACTOR"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "Generated build-info.json"
|
||||||
|
cat build-info.json
|
||||||
|
|
||||||
|
# Example 4: Use pre_push_hook for final validation
|
||||||
|
pre-push-validation-example:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Make changes
|
||||||
|
run: |
|
||||||
|
echo "Important data: $(date)" > important-file.txt
|
||||||
|
|
||||||
|
- name: Commit with pre-push validation
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
commit_message: "Add important file with validation"
|
||||||
|
pre_push_hook: |
|
||||||
|
echo "Running final validation before push..."
|
||||||
|
|
||||||
|
# Check if important file exists and has content
|
||||||
|
if [ ! -f "important-file.txt" ] || [ ! -s "important-file.txt" ]; then
|
||||||
|
echo "ERROR: important-file.txt is missing or empty!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check git log for the commit we're about to push
|
||||||
|
echo "Latest commit details:"
|
||||||
|
git log -1 --oneline
|
||||||
|
|
||||||
|
echo "Pre-push validation passed!"
|
||||||
|
|
||||||
|
# Example 5: Use post_push_hook for notifications
|
||||||
|
notification-example:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Update documentation
|
||||||
|
run: |
|
||||||
|
echo "# Documentation Updated" > README.md
|
||||||
|
echo "Last updated: $(date)" >> README.md
|
||||||
|
|
||||||
|
- name: Commit with notification hook
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
commit_message: "Update documentation"
|
||||||
|
post_push_hook: |
|
||||||
|
echo "Changes successfully pushed!"
|
||||||
|
|
||||||
|
# Get the commit hash that was just pushed
|
||||||
|
COMMIT_HASH=$(git rev-parse HEAD)
|
||||||
|
echo "Pushed commit: $COMMIT_HASH"
|
||||||
|
|
||||||
|
# Create a summary
|
||||||
|
echo "📝 Documentation updated successfully" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- Commit: \`$COMMIT_HASH\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- Time: $(date)" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
# In a real scenario, you might send notifications to Slack, Discord, etc.
|
||||||
|
echo "This is where you would send notifications to your team!"
|
||||||
|
|
||||||
|
# Example 6: Multiple hooks working together
|
||||||
|
comprehensive-example:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup environment
|
||||||
|
run: |
|
||||||
|
echo "Setting up project..."
|
||||||
|
mkdir -p logs
|
||||||
|
|
||||||
|
- name: Make changes
|
||||||
|
run: |
|
||||||
|
echo "Feature implementation" > feature.txt
|
||||||
|
echo "$(date): Feature added" > logs/changes.log
|
||||||
|
|
||||||
|
- name: Commit with all hooks
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
commit_message: "Add comprehensive feature"
|
||||||
|
pre_status_hook: |
|
||||||
|
echo "🔍 Pre-status: Preparing repository..."
|
||||||
|
git status --porcelain
|
||||||
|
|
||||||
|
pre_commit_hook: |
|
||||||
|
echo "🛠️ Pre-commit: Generating metadata..."
|
||||||
|
|
||||||
|
# Generate changelog entry
|
||||||
|
echo "## $(date +%Y-%m-%d)" > CHANGELOG_ENTRY.md
|
||||||
|
echo "- Added comprehensive feature" >> CHANGELOG_ENTRY.md
|
||||||
|
|
||||||
|
# Update version file
|
||||||
|
echo "1.0.$(date +%s)" > VERSION
|
||||||
|
|
||||||
|
pre_push_hook: |
|
||||||
|
echo "✅ Pre-push: Final validation..."
|
||||||
|
|
||||||
|
# Validate all required files exist
|
||||||
|
required_files=("feature.txt" "logs/changes.log" "CHANGELOG_ENTRY.md" "VERSION")
|
||||||
|
for file in "${required_files[@]}"; do
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
echo "ERROR: Required file $file is missing!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "All validations passed!"
|
||||||
|
|
||||||
|
post_push_hook: |
|
||||||
|
echo "🎉 Post-push: Cleanup and notification..."
|
||||||
|
|
||||||
|
# Clean up temporary files if any
|
||||||
|
rm -f /tmp/build-*
|
||||||
|
|
||||||
|
# Log success
|
||||||
|
echo "Deployment completed at $(date)" >> logs/deployment.log
|
||||||
|
|
||||||
|
echo "Comprehensive feature deployment completed!"
|
||||||
|
|
||||||
|
# Example 7: Error handling demonstration
|
||||||
|
error-handling-example:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Make changes
|
||||||
|
run: |
|
||||||
|
echo "Some changes" > test-file.txt
|
||||||
|
|
||||||
|
- name: Demonstrate hook failure (this will fail)
|
||||||
|
uses: ./
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
commit_message: "This commit should fail"
|
||||||
|
pre_commit_hook: |
|
||||||
|
echo "Running validation that will fail..."
|
||||||
|
|
||||||
|
# This will cause the hook to fail
|
||||||
|
if [ "$(cat test-file.txt)" = "Some changes" ]; then
|
||||||
|
echo "ERROR: File content not allowed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Show that workflow continues after failure
|
||||||
|
run: |
|
||||||
|
echo "This step runs even if the previous step failed due to continue-on-error: true"
|
||||||
159
README.md
159
README.md
@@ -244,6 +244,165 @@ If you would like to prevent this, you can add `skip-checks:true` to the commit
|
|||||||
|
|
||||||
Does your workflow change a file, but "git-auto-commit" does not detect the change? Check the `.gitignore` that applies to the respective file. You might have accidentally marked the file to be ignored by git.
|
Does your workflow change a file, but "git-auto-commit" does not detect the change? Check the `.gitignore` that applies to the respective file. You might have accidentally marked the file to be ignored by git.
|
||||||
|
|
||||||
|
## Hooks
|
||||||
|
|
||||||
|
The action supports custom bash scripts that can be executed at various points during the git workflow. This allows for custom preparation, validation, or post-processing steps.
|
||||||
|
|
||||||
|
### Available Hooks
|
||||||
|
|
||||||
|
- **`pre_status_hook`** - Executed before checking git status. Useful for repository preparation like `git fetch --unshallow`.
|
||||||
|
- **`pre_commit_hook`** - Executed after detecting changes but before adding files. Allows modification of files that will be included in the commit.
|
||||||
|
- **`pre_push_hook`** - Executed after committing but before pushing to remote. Useful for final validation.
|
||||||
|
- **`post_push_hook`** - Executed after successfully pushing changes. Useful for notifications or cleanup.
|
||||||
|
|
||||||
|
### Hook Examples
|
||||||
|
|
||||||
|
#### Unshallow Repository Before Checking Status
|
||||||
|
|
||||||
|
This example addresses the common issue where workflows use shallow checkouts (`fetch-depth: 1`) for performance, but need to unshallow before merging or when full history is required for certain operations.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Update Submodules
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-submodules:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 1 # Shallow checkout for performance
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Update submodule to latest
|
||||||
|
run: |
|
||||||
|
git submodule update --remote
|
||||||
|
|
||||||
|
- name: Commit submodule updates
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v6
|
||||||
|
with:
|
||||||
|
file_pattern: .gitmodules *
|
||||||
|
commit_message: "Update submodules to latest versions"
|
||||||
|
pre_status_hook: |
|
||||||
|
# Only unshallow if we have changes and need to merge
|
||||||
|
if git status --porcelain | grep -q .; then
|
||||||
|
echo "Changes detected, checking if repository is shallow..."
|
||||||
|
if git rev-parse --is-shallow-repository 2>/dev/null | grep -q true; then
|
||||||
|
echo "Repository is shallow, running git fetch --unshallow"
|
||||||
|
git fetch --unshallow
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Addressing "refusing to merge unrelated histories" Error
|
||||||
|
|
||||||
|
This specific example addresses the use case discussed in [GitHub Issue #365](https://github.com/stefanzweifel/git-auto-commit-action/discussions/365), where shallow repositories can cause merge conflicts:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Update Dependencies with Unshallow
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * 1' # Weekly updates
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-deps:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 1 # Start with shallow clone for performance
|
||||||
|
|
||||||
|
- name: Update dependencies
|
||||||
|
run: |
|
||||||
|
# Your dependency update commands here
|
||||||
|
npm update
|
||||||
|
# or pip install -r requirements.txt --upgrade
|
||||||
|
# or bundle update
|
||||||
|
|
||||||
|
- name: Commit dependency updates
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v6
|
||||||
|
with:
|
||||||
|
file_pattern: 'package*.json yarn.lock requirements.txt Gemfile.lock'
|
||||||
|
commit_message: 'Update dependencies'
|
||||||
|
pre_status_hook: |
|
||||||
|
# Check if repository is shallow and unshallow if changes are detected
|
||||||
|
if git status --porcelain | grep -q .; then
|
||||||
|
echo "Dependencies have been updated, checking repository depth..."
|
||||||
|
if git rev-parse --is-shallow-repository 2>/dev/null | grep -q true; then
|
||||||
|
echo "Repository is shallow ($(git rev-list --count HEAD) commits), running git fetch --unshallow"
|
||||||
|
git fetch --unshallow
|
||||||
|
echo "Repository unshallowed successfully"
|
||||||
|
else
|
||||||
|
echo "Repository is not shallow ($(git rev-list --count HEAD) commits)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "No dependency changes detected, skipping unshallow"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Validate Files Before Committing
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Commit with validation
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v6
|
||||||
|
with:
|
||||||
|
commit_message: Apply automatic changes
|
||||||
|
pre_commit_hook: |
|
||||||
|
echo "Running validation..."
|
||||||
|
npm run lint
|
||||||
|
npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Generate Additional Files in Pre-Commit Hook
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Commit with file generation
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v6
|
||||||
|
with:
|
||||||
|
commit_message: Update files and manifest
|
||||||
|
pre_commit_hook: |
|
||||||
|
echo "Generating manifest..."
|
||||||
|
echo "Build timestamp: $(date)" > build-info.txt
|
||||||
|
echo "Commit: $GITHUB_SHA" >> build-info.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Notify After Successful Push
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Commit and notify
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v6
|
||||||
|
with:
|
||||||
|
commit_message: Apply automatic changes
|
||||||
|
post_push_hook: |
|
||||||
|
echo "Changes successfully pushed!"
|
||||||
|
curl -X POST -H 'Content-type: application/json' \
|
||||||
|
--data '{"text":"Code changes have been committed and pushed"}' \
|
||||||
|
"$SLACK_WEBHOOK_URL"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hook Error Handling
|
||||||
|
|
||||||
|
If any hook fails (exits with non-zero status), the entire action will fail and stop execution. This ensures that validation hooks can prevent commits/pushes when issues are detected.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Commit with strict validation
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v6
|
||||||
|
with:
|
||||||
|
commit_message: Apply automatic changes
|
||||||
|
pre_commit_hook: |
|
||||||
|
# This will fail the action if any .js files have syntax errors
|
||||||
|
find . -name "*.js" -exec node -c {} \;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hook Execution Context
|
||||||
|
|
||||||
|
- Hooks are executed in the repository directory
|
||||||
|
- Hooks have access to all git commands and repository state
|
||||||
|
- Hooks can access GitHub Actions environment variables
|
||||||
|
- Files created/modified by `pre_commit_hook` will be included in the commit
|
||||||
|
- Hooks run in bash and support multi-line scripts
|
||||||
|
|
||||||
## Advanced Uses
|
## Advanced Uses
|
||||||
|
|
||||||
### Multiline Commit Messages
|
### Multiline Commit Messages
|
||||||
|
|||||||
39
action.yml
39
action.yml
@@ -1,5 +1,5 @@
|
|||||||
name: Git Auto Commit
|
name: Git Auto Commit
|
||||||
description: 'Automatically commits files which have been changed during the workflow run and push changes back to remote repository.'
|
description: "Automatically commits files which have been changed during the workflow run and push changes back to remote repository."
|
||||||
|
|
||||||
author: Stefan Zweifel <stefan@stefanzweifel.dev>
|
author: Stefan Zweifel <stefan@stefanzweifel.dev>
|
||||||
|
|
||||||
@@ -15,23 +15,23 @@ inputs:
|
|||||||
commit_options:
|
commit_options:
|
||||||
description: Commit options (eg. --no-verify)
|
description: Commit options (eg. --no-verify)
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
add_options:
|
add_options:
|
||||||
description: Add options (eg. -u)
|
description: Add options (eg. -u)
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
status_options:
|
status_options:
|
||||||
description: Status options (eg. --untracked-files=no)
|
description: Status options (eg. --untracked-files=no)
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
file_pattern:
|
file_pattern:
|
||||||
description: File pattern used for `git add`. For example `src/*.js`
|
description: File pattern used for `git add`. For example `src/*.js`
|
||||||
required: false
|
required: false
|
||||||
default: '.'
|
default: "."
|
||||||
repository:
|
repository:
|
||||||
description: Local file path to the git repository. Defaults to the current directory (`.`)
|
description: Local file path to the git repository. Defaults to the current directory (`.`)
|
||||||
required: false
|
required: false
|
||||||
default: '.'
|
default: "."
|
||||||
commit_user_name:
|
commit_user_name:
|
||||||
description: Name used for the commit user
|
description: Name used for the commit user
|
||||||
required: false
|
required: false
|
||||||
@@ -47,11 +47,11 @@ inputs:
|
|||||||
tagging_message:
|
tagging_message:
|
||||||
description: Message used to create a new git tag with the commit. Keep this empty, if no tag should be created.
|
description: Message used to create a new git tag with the commit. Keep this empty, if no tag should be created.
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
push_options:
|
push_options:
|
||||||
description: Push options (eg. --force)
|
description: Push options (eg. --force)
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
skip_dirty_check:
|
skip_dirty_check:
|
||||||
description: Skip the check if the git repository is dirty and always try to create a commit.
|
description: Skip the check if the git repository is dirty and always try to create a commit.
|
||||||
required: false
|
required: false
|
||||||
@@ -66,6 +66,22 @@ inputs:
|
|||||||
internal_git_binary:
|
internal_git_binary:
|
||||||
description: Internal use only! Path to git binary used to check if git is available. (Don't change this!)
|
description: Internal use only! Path to git binary used to check if git is available. (Don't change this!)
|
||||||
default: git
|
default: git
|
||||||
|
pre_status_hook:
|
||||||
|
description: Bash script to execute before checking git status. Useful for git fetch --unshallow or other repository preparation.
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
pre_commit_hook:
|
||||||
|
description: Bash script to execute before committing changes. Useful for validation or last-minute file modifications.
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
pre_push_hook:
|
||||||
|
description: Bash script to execute before pushing changes to remote. Useful for final validation.
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
post_push_hook:
|
||||||
|
description: Bash script to execute after successfully pushing changes. Useful for notifications or cleanup.
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
skip_fetch:
|
skip_fetch:
|
||||||
description: "Deprecated: skip_fetch has been removed in v6. It does not have any effect anymore."
|
description: "Deprecated: skip_fetch has been removed in v6. It does not have any effect anymore."
|
||||||
required: false
|
required: false
|
||||||
@@ -78,7 +94,6 @@ inputs:
|
|||||||
description: "Deprecated: create_branch has been removed in v6. It does not have any effect anymore."
|
description: "Deprecated: create_branch has been removed in v6. It does not have any effect anymore."
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
changes_detected:
|
changes_detected:
|
||||||
description: Value is "true", if the repository was dirty and file changes have been detected. Value is "false", if no changes have been detected.
|
description: Value is "true", if the repository was dirty and file changes have been detected. Value is "false", if no changes have been detected.
|
||||||
@@ -88,9 +103,9 @@ outputs:
|
|||||||
description: Value is "true", if a git tag was created using the `create_git_tag_only`-input.
|
description: Value is "true", if a git tag was created using the `create_git_tag_only`-input.
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: "node20"
|
||||||
main: 'index.js'
|
main: "index.js"
|
||||||
|
|
||||||
branding:
|
branding:
|
||||||
icon: 'git-commit'
|
icon: "git-commit"
|
||||||
color: orange
|
color: orange
|
||||||
|
|||||||
@@ -19,6 +19,32 @@ _set_github_output() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_execute_hook() {
|
||||||
|
local hook_name=${1}
|
||||||
|
local hook_script=${2}
|
||||||
|
|
||||||
|
if [ -n "$hook_script" ]; then
|
||||||
|
_log "debug" "Executing $hook_name hook";
|
||||||
|
echo "::group::$hook_name hook"
|
||||||
|
|
||||||
|
# Execute the hook script and capture exit code
|
||||||
|
# Temporarily disable errexit to handle hook failures gracefully
|
||||||
|
set +e
|
||||||
|
eval "$hook_script"
|
||||||
|
local exit_code=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [ $exit_code -ne 0 ]; then
|
||||||
|
_log "error" "$hook_name hook failed with exit code $exit_code";
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
_log "debug" "$hook_name hook completed successfully";
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
_log() {
|
_log() {
|
||||||
local level=${1}
|
local level=${1}
|
||||||
local message=${2}
|
local message=${2}
|
||||||
@@ -47,15 +73,28 @@ _main() {
|
|||||||
|
|
||||||
# _check_if_repository_is_in_detached_state
|
# _check_if_repository_is_in_detached_state
|
||||||
|
|
||||||
|
# Execute pre-status hook before checking repository state
|
||||||
|
_execute_hook "pre_status" "$INPUT_PRE_STATUS_HOOK"
|
||||||
|
|
||||||
if "$INPUT_CREATE_GIT_TAG_ONLY"; then
|
if "$INPUT_CREATE_GIT_TAG_ONLY"; then
|
||||||
_log "debug" "Create git tag only";
|
_log "debug" "Create git tag only";
|
||||||
_set_github_output "create_git_tag_only" "true"
|
_set_github_output "create_git_tag_only" "true"
|
||||||
_tag_commit
|
_tag_commit
|
||||||
|
|
||||||
|
# Execute pre-push hook before pushing (tag-only mode)
|
||||||
|
_execute_hook "pre_push" "$INPUT_PRE_PUSH_HOOK"
|
||||||
|
|
||||||
_push_to_github
|
_push_to_github
|
||||||
|
|
||||||
|
# Execute post-push hook after successful push (tag-only mode)
|
||||||
|
_execute_hook "post_push" "$INPUT_POST_PUSH_HOOK"
|
||||||
elif _git_is_dirty || "$INPUT_SKIP_DIRTY_CHECK"; then
|
elif _git_is_dirty || "$INPUT_SKIP_DIRTY_CHECK"; then
|
||||||
|
|
||||||
_set_github_output "changes_detected" "true"
|
_set_github_output "changes_detected" "true"
|
||||||
|
|
||||||
|
# Execute pre-commit hook before adding files so hook can modify files
|
||||||
|
_execute_hook "pre_commit" "$INPUT_PRE_COMMIT_HOOK"
|
||||||
|
|
||||||
_add_files
|
_add_files
|
||||||
|
|
||||||
# Check dirty state of repo again using git-diff.
|
# Check dirty state of repo again using git-diff.
|
||||||
@@ -67,7 +106,13 @@ _main() {
|
|||||||
|
|
||||||
_tag_commit
|
_tag_commit
|
||||||
|
|
||||||
|
# Execute pre-push hook before pushing
|
||||||
|
_execute_hook "pre_push" "$INPUT_PRE_PUSH_HOOK"
|
||||||
|
|
||||||
_push_to_github
|
_push_to_github
|
||||||
|
|
||||||
|
# Execute post-push hook after successful push
|
||||||
|
_execute_hook "post_push" "$INPUT_POST_PUSH_HOOK"
|
||||||
else
|
else
|
||||||
_set_github_output "changes_detected" "false"
|
_set_github_output "changes_detected" "false"
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ setup() {
|
|||||||
export INPUT_DISABLE_GLOBBING=false
|
export INPUT_DISABLE_GLOBBING=false
|
||||||
export INPUT_INTERNAL_GIT_BINARY=git
|
export INPUT_INTERNAL_GIT_BINARY=git
|
||||||
|
|
||||||
|
# Hook variables
|
||||||
|
export INPUT_PRE_STATUS_HOOK=""
|
||||||
|
export INPUT_PRE_COMMIT_HOOK=""
|
||||||
|
export INPUT_PRE_PUSH_HOOK=""
|
||||||
|
export INPUT_POST_PUSH_HOOK=""
|
||||||
|
|
||||||
# Deprecated variables. Will be removed in future versions
|
# Deprecated variables. Will be removed in future versions
|
||||||
export INPUT_CREATE_BRANCH=false
|
export INPUT_CREATE_BRANCH=false
|
||||||
export INPUT_SKIP_FETCH=false
|
export INPUT_SKIP_FETCH=false
|
||||||
@@ -1181,3 +1187,235 @@ END
|
|||||||
assert_line "::warning::git-auto-commit: skip_checkout has been removed in v6. It does not have any effect anymore."
|
assert_line "::warning::git-auto-commit: skip_checkout has been removed in v6. It does not have any effect anymore."
|
||||||
assert_line "::warning::git-auto-commit: create_branch has been removed in v6. It does not have any effect anymore."
|
assert_line "::warning::git-auto-commit: create_branch has been removed in v6. It does not have any effect anymore."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "it executes pre_status_hook when provided" {
|
||||||
|
# Create a dummy file and setup the hook to create a marker file
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file-created-by-hook.txt
|
||||||
|
|
||||||
|
INPUT_PRE_STATUS_HOOK="echo 'pre-status-hook-executed' > hook-marker.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing pre_status hook"
|
||||||
|
assert_line "::debug::pre_status hook completed successfully"
|
||||||
|
|
||||||
|
# Verify the hook actually executed
|
||||||
|
assert [ -f "${FAKE_LOCAL_REPOSITORY}/hook-marker.txt" ]
|
||||||
|
run cat "${FAKE_LOCAL_REPOSITORY}/hook-marker.txt"
|
||||||
|
assert_output "pre-status-hook-executed"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it executes pre_commit_hook when changes are detected" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file-created-by-hook.txt
|
||||||
|
|
||||||
|
INPUT_PRE_COMMIT_HOOK="echo 'pre-commit-hook-executed' > pre-commit-marker.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing pre_commit hook"
|
||||||
|
assert_line "::debug::pre_commit hook completed successfully"
|
||||||
|
|
||||||
|
# Verify the hook actually executed
|
||||||
|
assert [ -f "${FAKE_LOCAL_REPOSITORY}/pre-commit-marker.txt" ]
|
||||||
|
run cat "${FAKE_LOCAL_REPOSITORY}/pre-commit-marker.txt"
|
||||||
|
assert_output "pre-commit-hook-executed"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it executes pre_push_hook when changes are detected" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file.txt
|
||||||
|
|
||||||
|
INPUT_PRE_PUSH_HOOK="echo 'pre-push-hook-executed' > pre-push-marker.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing pre_push hook"
|
||||||
|
assert_line "::debug::pre_push hook completed successfully"
|
||||||
|
|
||||||
|
# Verify the hook actually executed
|
||||||
|
assert [ -f "${FAKE_LOCAL_REPOSITORY}/pre-push-marker.txt" ]
|
||||||
|
run cat "${FAKE_LOCAL_REPOSITORY}/pre-push-marker.txt"
|
||||||
|
assert_output "pre-push-hook-executed"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it executes post_push_hook when changes are detected" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file.txt
|
||||||
|
|
||||||
|
INPUT_POST_PUSH_HOOK="echo 'post-push-hook-executed' > post-push-marker.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing post_push hook"
|
||||||
|
assert_line "::debug::post_push hook completed successfully"
|
||||||
|
|
||||||
|
# Verify the hook actually executed
|
||||||
|
assert [ -f "${FAKE_LOCAL_REPOSITORY}/post-push-marker.txt" ]
|
||||||
|
run cat "${FAKE_LOCAL_REPOSITORY}/post-push-marker.txt"
|
||||||
|
assert_output "post-push-hook-executed"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it executes all hooks in correct order when changes are detected" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file.txt
|
||||||
|
|
||||||
|
INPUT_PRE_STATUS_HOOK="echo '1' > execution-order.txt"
|
||||||
|
INPUT_PRE_COMMIT_HOOK="echo '2' >> execution-order.txt"
|
||||||
|
INPUT_PRE_PUSH_HOOK="echo '3' >> execution-order.txt"
|
||||||
|
INPUT_POST_PUSH_HOOK="echo '4' >> execution-order.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing pre_status hook"
|
||||||
|
assert_line "::debug::Executing pre_commit hook"
|
||||||
|
assert_line "::debug::Executing pre_push hook"
|
||||||
|
assert_line "::debug::Executing post_push hook"
|
||||||
|
|
||||||
|
# Verify all hooks executed in the correct order
|
||||||
|
run cat "${FAKE_LOCAL_REPOSITORY}/execution-order.txt"
|
||||||
|
assert_line --index 0 "1"
|
||||||
|
assert_line --index 1 "2"
|
||||||
|
assert_line --index 2 "3"
|
||||||
|
assert_line --index 3 "4"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it executes pre_status_hook even when no changes are detected" {
|
||||||
|
INPUT_PRE_STATUS_HOOK="echo 'pre-status-hook-executed' > /tmp/hook-marker.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing pre_status hook"
|
||||||
|
assert_line "Working tree clean. Nothing to commit."
|
||||||
|
|
||||||
|
# Verify the hook actually executed
|
||||||
|
assert [ -f "/tmp/hook-marker.txt" ]
|
||||||
|
run cat "/tmp/hook-marker.txt"
|
||||||
|
assert_output "pre-status-hook-executed"
|
||||||
|
rm -f "/tmp/hook-marker.txt"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it does not execute commit/push hooks when no changes are detected" {
|
||||||
|
INPUT_PRE_COMMIT_HOOK="echo 'should-not-execute' > pre-commit-marker.txt"
|
||||||
|
INPUT_PRE_PUSH_HOOK="echo 'should-not-execute' > pre-push-marker.txt"
|
||||||
|
INPUT_POST_PUSH_HOOK="echo 'should-not-execute' > post-push-marker.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "Working tree clean. Nothing to commit."
|
||||||
|
|
||||||
|
# Verify the hooks did not execute
|
||||||
|
assert [ ! -f "${FAKE_LOCAL_REPOSITORY}/pre-commit-marker.txt" ]
|
||||||
|
assert [ ! -f "${FAKE_LOCAL_REPOSITORY}/pre-push-marker.txt" ]
|
||||||
|
assert [ ! -f "${FAKE_LOCAL_REPOSITORY}/post-push-marker.txt" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it executes hooks in tag-only mode" {
|
||||||
|
INPUT_CREATE_GIT_TAG_ONLY=true
|
||||||
|
INPUT_TAGGING_MESSAGE="v1.0.0"
|
||||||
|
INPUT_PRE_STATUS_HOOK="echo 'pre-status-tag-only' > pre-status-marker.txt"
|
||||||
|
INPUT_PRE_PUSH_HOOK="echo 'pre-push-tag-only' > pre-push-marker.txt"
|
||||||
|
INPUT_POST_PUSH_HOOK="echo 'post-push-tag-only' > post-push-marker.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing pre_status hook"
|
||||||
|
assert_line "::debug::Executing pre_push hook"
|
||||||
|
assert_line "::debug::Executing post_push hook"
|
||||||
|
|
||||||
|
# Verify hooks executed
|
||||||
|
assert [ -f "${FAKE_LOCAL_REPOSITORY}/pre-status-marker.txt" ]
|
||||||
|
assert [ -f "${FAKE_LOCAL_REPOSITORY}/pre-push-marker.txt" ]
|
||||||
|
assert [ -f "${FAKE_LOCAL_REPOSITORY}/post-push-marker.txt" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it fails when pre_status_hook fails" {
|
||||||
|
INPUT_PRE_STATUS_HOOK="false"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_failure
|
||||||
|
assert_line "::debug::Executing pre_status hook"
|
||||||
|
assert_line "::error::pre_status hook failed with exit code 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it fails when pre_commit_hook fails" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file.txt
|
||||||
|
|
||||||
|
INPUT_PRE_COMMIT_HOOK="false"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_failure
|
||||||
|
assert_line "::debug::Executing pre_commit hook"
|
||||||
|
assert_line "::error::pre_commit hook failed with exit code 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it fails when pre_push_hook fails" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file.txt
|
||||||
|
|
||||||
|
INPUT_PRE_PUSH_HOOK="false"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_failure
|
||||||
|
assert_line "::debug::Executing pre_push hook"
|
||||||
|
assert_line "::error::pre_push hook failed with exit code 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "it fails when post_push_hook fails" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file.txt
|
||||||
|
|
||||||
|
INPUT_POST_PUSH_HOOK="false"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_failure
|
||||||
|
assert_line "::debug::Executing post_push hook"
|
||||||
|
assert_line "::error::post_push hook failed with exit code 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "hook can access git commands and repository state" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file.txt
|
||||||
|
|
||||||
|
INPUT_PRE_COMMIT_HOOK="git log --oneline | head -1 > git-log-output.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing pre_commit hook"
|
||||||
|
|
||||||
|
# Verify the hook could access git commands
|
||||||
|
assert [ -f "${FAKE_LOCAL_REPOSITORY}/git-log-output.txt" ]
|
||||||
|
run cat "${FAKE_LOCAL_REPOSITORY}/git-log-output.txt"
|
||||||
|
assert_line --partial "Init Remote Repository"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "hook can modify files that get included in commit" {
|
||||||
|
# Create a dummy file to trigger commit process
|
||||||
|
touch "${FAKE_LOCAL_REPOSITORY}"/new-file.txt
|
||||||
|
|
||||||
|
INPUT_PRE_COMMIT_HOOK="echo 'modified by hook' > hook-modified-file.txt"
|
||||||
|
|
||||||
|
run git_auto_commit
|
||||||
|
|
||||||
|
assert_success
|
||||||
|
assert_line "::debug::Executing pre_commit hook"
|
||||||
|
|
||||||
|
# Verify the file created by the hook was committed
|
||||||
|
run git log --name-only -1
|
||||||
|
assert_line "hook-modified-file.txt"
|
||||||
|
assert_line "new-file.txt"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user