---
name: Gitflow Validation
# Only validate on PRs to avoid redundant runs
# Branch name validation happens when PR is opened/updated
"on":
pull_request:
types: [opened, reopened, synchronize, edited]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
validate-branch-name:
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- name: Validate branch name follows gitflow convention
env:
BRANCH_NAME: ${{ github.head_ref }}
run: |
echo "Validating branch: $BRANCH_NAME"
# Allow main and develop
if [[ "$BRANCH_NAME" == "main" ]] || \
[[ "$BRANCH_NAME" == "develop" ]]; then
echo "✓ Protected branch: $BRANCH_NAME"
exit 0
fi
# Allow dependabot branches (automated dependency updates)
if [[ "$BRANCH_NAME" =~ ^dependabot/.+ ]]; then
echo "✓ Valid dependabot branch: $BRANCH_NAME"
exit 0
fi
# Validate gitflow branch naming
if [[ "$BRANCH_NAME" =~ ^feature/.+ ]]; then
echo "✓ Valid feature branch: $BRANCH_NAME"
elif [[ "$BRANCH_NAME" =~ ^release/.+ ]]; then
echo "✓ Valid release branch: $BRANCH_NAME"
elif [[ "$BRANCH_NAME" =~ ^hotfix/.+ ]]; then
echo "✓ Valid hotfix branch: $BRANCH_NAME"
elif [[ "$BRANCH_NAME" =~ ^bugfix/.+ ]]; then
echo "✓ Valid bugfix branch: $BRANCH_NAME"
elif [[ "$BRANCH_NAME" =~ ^support/.+ ]]; then
echo "✓ Valid support branch: $BRANCH_NAME"
else
echo "✗ Invalid branch name: $BRANCH_NAME"
echo ""
echo "Branch names must follow gitflow conventions:"
echo " - feature/<description> (for new features)"
echo " - bugfix/<description> (for bug fixes)"
echo " - release/<version> (for release prep)"
echo " - hotfix/<version> (for production fixes)"
echo " - support/<description> (for support branches)"
echo " - dependabot/* (automated dependency updates)"
echo ""
echo "Examples:"
echo " - feature/add-ansible-support"
echo " - bugfix/fix-parser-error"
echo " - release/1.2.0"
echo " - hotfix/1.1.1"
exit 1
fi
validate-pr-base:
runs-on: ubuntu-latest
timeout-minutes: 5
if: github.event_name == 'pull_request'
permissions:
contents: read
steps:
- name: Validate PR target branch matches gitflow rules
env:
SOURCE_BRANCH: ${{ github.head_ref }}
TARGET_BRANCH: ${{ github.base_ref }}
run: |
echo "PR: $SOURCE_BRANCH → $TARGET_BRANCH"
# Main should never merge to develop (wrong direction)
if [[ "$SOURCE_BRANCH" == "main" ]]; then
echo "✗ Main branch cannot be used as source for PRs"
echo " Releases cut from main, not merged back"
exit 1
fi
# Feature branches must target develop
if [[ "$SOURCE_BRANCH" =~ ^feature/.+ ]]; then
if [[ "$TARGET_BRANCH" != "develop" ]]; then
echo "✗ Feature branches must target 'develop',"
echo " not '$TARGET_BRANCH'"
exit 1
fi
echo "✓ Feature branch correctly targets develop"
fi
# Bugfix branches must target develop
if [[ "$SOURCE_BRANCH" =~ ^bugfix/.+ ]]; then
if [[ "$TARGET_BRANCH" != "develop" ]]; then
echo "✗ Bugfix branches must target 'develop',"
echo " not '$TARGET_BRANCH'"
exit 1
fi
echo "✓ Bugfix branch correctly targets develop"
fi
# Support branches can target develop or main
if [[ "$SOURCE_BRANCH" =~ ^support/.+ ]]; then
if [[ "$TARGET_BRANCH" != "develop" ]] && \
[[ "$TARGET_BRANCH" != "main" ]]; then
echo "✗ Support must target 'develop' or 'main',"
echo " not '$TARGET_BRANCH'"
exit 1
fi
echo "✓ Support branch correctly targets $TARGET_BRANCH"
fi
# Release branches must target main
if [[ "$SOURCE_BRANCH" =~ ^release/.+ ]]; then
if [[ "$TARGET_BRANCH" != "main" ]]; then
echo "✗ Release branches must target 'main',"
echo " not '$TARGET_BRANCH'"
exit 1
fi
echo "✓ Release branch correctly targets main"
fi
# Hotfix branches must target main
if [[ "$SOURCE_BRANCH" =~ ^hotfix/.+ ]]; then
if [[ "$TARGET_BRANCH" != "main" ]]; then
echo "✗ Hotfix branches must target 'main',"
echo " not '$TARGET_BRANCH'"
exit 1
fi
echo "✓ Hotfix branch correctly targets main"
fi
# Develop can merge to main
if [[ "$SOURCE_BRANCH" == "develop" ]]; then
if [[ "$TARGET_BRANCH" != "main" ]]; then
echo "✗ Develop can only merge to 'main',"
echo " not '$TARGET_BRANCH'"
exit 1
fi
echo "✓ Develop correctly targets main"
fi
comment-pr-guidance:
runs-on: ubuntu-latest
timeout-minutes: 5
if: github.event_name == 'pull_request' && github.event.action == 'opened'
permissions:
pull-requests: write
steps:
- name: Comment gitflow guidance on new PRs
uses: actions/github-script@v8
with:
script: |
const pr = context.payload.pull_request;
const sourceBranch = pr.head.ref;
const targetBranch = pr.base.ref;
let branchType = 'unknown';
if (sourceBranch.startsWith('feature/'))
branchType = 'feature';
else if (sourceBranch.startsWith('bugfix/'))
branchType = 'bugfix';
else if (sourceBranch.startsWith('release/'))
branchType = 'release';
else if (sourceBranch.startsWith('hotfix/'))
branchType = 'hotfix';
else if (sourceBranch === 'develop')
branchType = 'develop';
const guidance = {
'feature': '🌟 **Feature**: Merge to `develop`, ' +
'then delete branch.',
'bugfix': '🐛 **Bugfix**: Merge to `develop`, ' +
'then delete branch.',
'release': '🚀 **Release**: Merge to `main`, ' +
'merge back to `develop`, tag release.',
'hotfix': '🔥 **Hotfix**: Merge to `main`, ' +
'merge back to `develop`, tag release.',
'develop': '🔄 **Develop → Main**: Release only. ' +
'Ensure all tests pass!'
};
if (guidance[branchType]) {
const body = `## Gitflow Validation
${guidance[branchType]}
### Checklist:
- [ ] All tests passing
- [ ] Code reviewed
- [ ] Documentation updated
- [ ] Changelog updated (if applicable)
---
_Automated gitflow guidance message._`;
await github.rest.issues.createComment({
issue_number: pr.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
}