Skip to content

Commit 3e9f68d

Browse files
Merge pull request #51 from contentstack/development
staging pr
2 parents 66d962b + 021a65c commit 3e9f68d

File tree

8 files changed

+350
-3
lines changed

8 files changed

+350
-3
lines changed

.husky/hooks/code-quality.sh

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env bash
2+
"""
3+
Code quality checking hook for Husky-style pre-commit setup.
4+
This hook runs Black, isort, flake8, and Bandit for code quality.
5+
"""
6+
7+
echo "🐍 Running Python code quality checks..."
8+
9+
# Function to check if a command exists
10+
command_exists() {
11+
command -v "$1" >/dev/null 2>&1
12+
}
13+
14+
# Check Black formatting
15+
echo " - Checking code formatting with Black..."
16+
if command_exists black; then
17+
if black --check --diff .; then
18+
echo " ✅ Black formatting check passed"
19+
else
20+
echo " ❌ Black formatting issues found"
21+
echo " 💡 Run 'black .' to fix formatting"
22+
exit 1
23+
fi
24+
else
25+
echo " ⚠️ Black not installed, skipping formatting check"
26+
echo " 💡 Install with: pip install black"
27+
fi
28+
29+
# Check isort import sorting
30+
echo " - Checking import sorting with isort..."
31+
if command_exists isort; then
32+
if isort --check-only --diff .; then
33+
echo " ✅ isort import sorting check passed"
34+
else
35+
echo " ❌ isort import sorting issues found"
36+
echo " 💡 Run 'isort .' to fix import sorting"
37+
exit 1
38+
fi
39+
else
40+
echo " ⚠️ isort not installed, skipping import sorting check"
41+
echo " 💡 Install with: pip install isort"
42+
fi
43+
44+
# Check flake8 linting
45+
echo " - Running linting with flake8..."
46+
if command_exists flake8; then
47+
if flake8 --max-line-length=88 --extend-ignore=E203,W503 .; then
48+
echo " ✅ flake8 linting check passed"
49+
else
50+
echo " ❌ flake8 linting issues found"
51+
echo " 💡 Fix the linting issues above"
52+
exit 1
53+
fi
54+
else
55+
echo " ⚠️ flake8 not installed, skipping linting check"
56+
echo " 💡 Install with: pip install flake8"
57+
fi
58+
59+
# Check Bandit security linting
60+
echo " - Running security linting with Bandit..."
61+
if command_exists bandit; then
62+
if bandit -r . -f json -o bandit-report.json; then
63+
echo " ✅ Bandit security linting check passed"
64+
else
65+
echo " ❌ Bandit found security issues"
66+
echo " 💡 Review bandit-report.json for details"
67+
exit 1
68+
fi
69+
else
70+
echo " ⚠️ Bandit not installed, skipping security linting"
71+
echo " 💡 Install with: pip install bandit"
72+
fi
73+
74+
echo "✅ All code quality checks passed!"

.husky/hooks/snyk-scan.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Snyk security scanning hook for Husky-style pre-commit setup.
4+
This hook runs Snyk security scanning on Python dependencies.
5+
"""
6+
7+
import os
8+
import sys
9+
import subprocess
10+
import json
11+
from pathlib import Path
12+
13+
14+
def run_snyk_scan():
15+
"""Run Snyk security scan on Python dependencies."""
16+
17+
# Check if Snyk CLI is available
18+
try:
19+
subprocess.run(['snyk', '--version'], capture_output=True, check=True)
20+
except (subprocess.CalledProcessError, FileNotFoundError):
21+
print("❌ Snyk CLI not found. Please install it first:")
22+
print(" npm install -g snyk")
23+
print(" or visit: https://snyk.io/docs/using-snyk/")
24+
return 1
25+
26+
# Check if SNYK_TOKEN is set
27+
if not os.getenv('SNYK_TOKEN'):
28+
print("⚠️ SNYK_TOKEN environment variable not set.")
29+
print(" Please set it with: export SNYK_TOKEN=your_token")
30+
print(" You can get a token from: https://app.snyk.io/account")
31+
return 0 # Don't fail the commit, just warn
32+
33+
# Check for requirements.txt
34+
requirements_files = ['requirements.txt', 'setup.py']
35+
found_requirements = False
36+
37+
for req_file in requirements_files:
38+
if Path(req_file).exists():
39+
found_requirements = True
40+
break
41+
42+
if not found_requirements:
43+
print("⚠️ No requirements.txt or setup.py found. Skipping Snyk scan.")
44+
return 0
45+
46+
print("🔍 Running Snyk security scan...")
47+
48+
try:
49+
# Run Snyk test on Python dependencies
50+
result = subprocess.run([
51+
'snyk', 'test',
52+
'--severity-threshold=high',
53+
'--json'
54+
], capture_output=True, text=True, check=False)
55+
56+
if result.returncode == 0:
57+
print("✅ Snyk scan completed - no high severity vulnerabilities found")
58+
return 0
59+
else:
60+
# Parse JSON output to show vulnerabilities
61+
try:
62+
vulns = json.loads(result.stdout)
63+
if 'vulnerabilities' in vulns:
64+
print("❌ High severity vulnerabilities found:")
65+
for vuln in vulns['vulnerabilities']:
66+
if vuln.get('severity') == 'high':
67+
print(f" - {vuln.get('title', 'Unknown')} in {vuln.get('packageName', 'Unknown')}")
68+
print(f" CVSS Score: {vuln.get('cvssScore', 'N/A')}")
69+
print(f" More info: {vuln.get('url', 'N/A')}")
70+
print()
71+
72+
print("💡 To fix vulnerabilities, run: snyk wizard")
73+
return 1
74+
except json.JSONDecodeError:
75+
print("❌ Snyk scan failed with errors:")
76+
print(result.stderr)
77+
return 1
78+
79+
except Exception as e:
80+
print(f"❌ Error running Snyk scan: {e}")
81+
return 1
82+
83+
84+
if __name__ == '__main__':
85+
sys.exit(run_snyk_scan())

.husky/hooks/talisman-check.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bash
2+
"""
3+
Talisman secrets detection hook for Husky-style pre-commit setup.
4+
This hook runs Talisman to detect potential secrets in commits.
5+
"""
6+
7+
# Check if Talisman is available
8+
if ! command -v talisman &> /dev/null; then
9+
echo "❌ Talisman not found. Please install it first:"
10+
echo " # macOS"
11+
echo " brew install talisman"
12+
echo " # Linux"
13+
echo " curl -sL https://github.com/thoughtworks/talisman/releases/latest/download/talisman_linux_amd64 -o talisman"
14+
echo " chmod +x talisman"
15+
echo " sudo mv talisman /usr/local/bin/"
16+
exit 1
17+
fi
18+
19+
echo "🔐 Running Talisman secrets detection..."
20+
21+
# Run Talisman with pre-commit hook
22+
if talisman --githook pre-commit; then
23+
echo "✅ Talisman check passed - no secrets detected"
24+
exit 0
25+
else
26+
echo "❌ Talisman found potential secrets in your changes"
27+
echo ""
28+
echo "💡 To fix this:"
29+
echo "1. Review the files mentioned above"
30+
echo "2. Remove any actual secrets from your code"
31+
echo "3. If the file contains legitimate test data, add it to .talismanrc:"
32+
echo " talisman --checksum path/to/file"
33+
echo " # Then add the checksum to .talismanrc"
34+
exit 1
35+
fi

.husky/hooks/test-runner.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env bash
2+
"""
3+
Test runner hook for Husky-style pre-push setup.
4+
This hook runs tests and coverage checks before pushing.
5+
"""
6+
7+
echo "🧪 Running tests and coverage checks..."
8+
9+
# Function to check if a command exists
10+
command_exists() {
11+
command -v "$1" >/dev/null 2>&1
12+
}
13+
14+
# Check if pytest is available
15+
if ! command_exists pytest; then
16+
echo "❌ pytest not found. Please install it first:"
17+
echo " pip install pytest pytest-cov"
18+
exit 1
19+
fi
20+
21+
# Run tests
22+
echo " - Running tests..."
23+
if pytest --html=tests/test-report/test-report.html; then
24+
echo " ✅ All tests passed"
25+
else
26+
echo " ❌ Tests failed. Please fix before pushing."
27+
exit 1
28+
fi
29+
30+
# Run coverage check
31+
echo " - Checking test coverage..."
32+
if command_exists pytest; then
33+
if pytest --cov=contentstack_utils --cov-report=term-missing; then
34+
echo " ✅ Coverage check completed"
35+
else
36+
echo " ❌ Coverage check failed. Please improve test coverage."
37+
exit 1
38+
fi
39+
else
40+
echo " ⚠️ pytest-cov not installed, skipping coverage check"
41+
echo " 💡 Install with: pip install pytest-cov"
42+
fi
43+
44+
echo "✅ All test checks passed!"

.husky/pre-commit

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env sh
2+
# Pre-commit hook to run Talisman and Snyk scans, completing both before deciding to commit
3+
4+
# Function to check if a command exists
5+
command_exists() {
6+
command -v "$1" >/dev/null 2>&1
7+
}
8+
9+
# Check if Talisman is installed
10+
if ! command_exists talisman; then
11+
echo "Error: Talisman is not installed. Please install it and try again."
12+
exit 1
13+
fi
14+
15+
# Check if Snyk is installed
16+
if ! command_exists snyk; then
17+
echo "Error: Snyk is not installed. Please install it and try again."
18+
exit 1
19+
fi
20+
21+
# Allow bypassing the hook with an environment variable
22+
if [ "$SKIP_HOOK" = "1" ]; then
23+
echo "Skipping Talisman and Snyk scans (SKIP_HOOK=1)."
24+
exit 0
25+
fi
26+
27+
# Initialize variables to track scan results
28+
talisman_failed=false
29+
snyk_failed=false
30+
31+
# Run Talisman secret scan
32+
echo "Running Talisman secret scan..."
33+
talisman --githook pre-commit > talisman_output.log 2>&1
34+
talisman_exit_code=$?
35+
36+
if [ $talisman_exit_code -eq 0 ]; then
37+
echo "Talisman scan passed: No secrets found."
38+
else
39+
echo "Talisman scan failed (exit code $talisman_exit_code). See talisman_output.log for details."
40+
talisman_failed=true
41+
fi
42+
43+
# Run Snyk vulnerability scan (continues even if Talisman failed)
44+
echo "Running Snyk vulnerability scan..."
45+
snyk test --all-projects --fail-on=all > snyk_output.log 2>&1
46+
snyk_exit_code=$?
47+
48+
if [ $snyk_exit_code -eq 0 ]; then
49+
echo "Snyk scan passed: No vulnerabilities found."
50+
elif [ $snyk_exit_code -eq 1 ]; then
51+
echo "Snyk found vulnerabilities. See snyk_output.log for details."
52+
snyk_failed=true
53+
else
54+
echo "Snyk scan failed with error (exit code $snyk_exit_code). See snyk_output.log for details."
55+
snyk_failed=true
56+
fi
57+
58+
# Evaluate results after both scans
59+
if [ "$talisman_failed" = true ] || [ "$snyk_failed" = true ]; then
60+
echo "Commit aborted due to issues found in one or both scans."
61+
[ "$talisman_failed" = true ] && echo "- Talisman issues: Check talisman_output.log"
62+
[ "$snyk_failed" = true ] && echo "- Snyk issues: Check snyk_output.log"
63+
exit 1
64+
fi
65+
66+
# If both scans pass, allow the commit
67+
echo "All scans passed. Proceeding with commit."
68+
rm -f talisman_output.log snyk_output.log
69+
exit 0

.husky/pre-push

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env sh
2+
3+
echo "🚀 Running pre-push checks..."
4+
5+
# Activate virtual environment if it exists
6+
if [ -d "venv" ]; then
7+
echo "🔧 Activating virtual environment..."
8+
source venv/bin/activate
9+
fi
10+
11+
# Run tests to ensure code quality
12+
echo "🧪 Running tests..."
13+
if ! pytest --html=tests/test-report/test-report.html; then
14+
echo "❌ Tests failed. Please fix before pushing."
15+
exit 1
16+
fi
17+
18+
# Run coverage check
19+
echo "📊 Checking test coverage..."
20+
if ! pytest --cov=contentstack_utils --cov-report=term-missing; then
21+
echo "❌ Coverage check failed. Please improve test coverage."
22+
exit 1
23+
fi
24+
25+
# Run security scan on dependencies (optional)
26+
if [ -n "$SNYK_TOKEN" ]; then
27+
echo "🔍 Running comprehensive Snyk scan..."
28+
if ! snyk test --severity-threshold=high; then
29+
echo "❌ High severity vulnerabilities found. Please fix before pushing."
30+
exit 1
31+
fi
32+
fi
33+
34+
echo "✅ All pre-push checks passed!"

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright 2021-2025 Contentstack
1+
Copyright 2021-2026 Contentstack
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
44

requirements.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
pip~=25.1.1
1+
pip~=26.0
22
setuptools==80.3.1
33
lxml~=5.4.0
4-
ruff==0.11.5
4+
ruff==0.11.5
5+
pytest>=7.0.0
6+
pytest-cov>=4.0.0
7+
pytest-html>=4.2.0
8+
black>=23.0.0
9+
flake8>=6.0.0
10+
isort>=5.0.0

0 commit comments

Comments
 (0)