Init commit

This commit is contained in:
2025-08-01 13:24:10 +03:00
commit b9f41bbda8
2 changed files with 123 additions and 0 deletions

35
README.md Normal file
View File

@@ -0,0 +1,35 @@
# Git Hooks
Коллекция моих собственных git hooks, написанных преимущественно на Python.
## Описание
Этот репозиторий содержит набор пользовательских git hooks для автоматизации проверок и обеспечения качества кода в процессе разработки.
## Структура
### pre-commit/
- **check-secrets-encrypted-with-ansible-vault.py** - Проверяет, что файлы с секретами (содержащие 'secret' или 'secrets' в имени) зашифрованы с помощью Ansible Vault перед коммитом
## Использование
### Ручная установка
1. Скопируйте нужный hook в директорию `.git/hooks/` вашего проекта
2. Переименуйте файл, убрав расширение (например, `pre-commit`)
3. Сделайте файл исполняемым: `chmod +x .git/hooks/pre-commit`
### Использование с lefthook
Hooks также можно использовать вместе с инструментом [lefthook](https://github.com/evilmartians/lefthook) для более удобного управления git hooks в проекте.
## Требования
- Python 3.x
- Git
- Для некоторых hooks могут потребоваться дополнительные зависимости (указаны в комментариях к файлам)
## Лицензия
Личная коллекция для собственного использования.

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env python3
"""
Pre-commit hook to prevent committing secret files that are not encrypted with Ansible Vault.
This hook checks if any staged files contain 'secret' or 'secrets' in their filename.
If such files are found and they don't start with '$ANSIBLE_VAULT', the commit is blocked.
"""
import sys
import subprocess
import os
ANSIBLE_VAULT_MARKER = '$ANSIBLE_VAULT'
def get_staged_files():
"""Get list of staged files for commit."""
try:
result = subprocess.run(
['git', 'diff', '--cached', '--name-only'],
capture_output=True,
text=True,
check=True
)
return result.stdout.strip().split('\n') if result.stdout.strip() else []
except subprocess.CalledProcessError as e:
print(f"Error getting staged files: {e}")
return []
def has_secret_in_name(filename):
"""Check if filename contains 'secret' or 'secrets'."""
basename = os.path.basename(filename).lower()
return 'secret' in basename or 'secrets' in basename
def is_ansible_vault_file(filepath):
"""Check if file starts with special vault marker."""
try:
if not os.path.exists(filepath):
return False
with open(filepath, 'r', encoding='utf-8') as f:
first_line = f.readline().strip()
return first_line.startswith(ANSIBLE_VAULT_MARKER)
except (IOError, UnicodeDecodeError):
# If we can't read the file or it's binary, assume it's not a vault file
return False
def main():
"""Main function to check staged files."""
staged_files = get_staged_files()
if not staged_files:
return 0
violations = []
for filepath in staged_files:
if has_secret_in_name(filepath):
if not is_ansible_vault_file(filepath):
violations.append(filepath)
if violations:
print("❌ COMMIT BLOCKED: Secret files must be encrypted with Ansible Vault!")
print("\nThe following files contain 'secret' or 'secrets' in their name")
print("but are not encrypted with Ansible Vault:")
print()
for violation in violations:
print(f"{violation}")
print()
print("To fix this issue:")
print("1. Encrypt the file(s) with: ansible-vault encrypt <filename>")
print("2. Or rename the file(s) to not contain 'secret' or 'secrets'")
print("3. Or add the file(s) to .gitignore if they shouldn't be committed")
print()
return 1
return 0
if __name__ == '__main__':
sys.exit(main())