Skip to content

Commit

Permalink
Add git hooks support (#8251)
Browse files Browse the repository at this point in the history
* test

* Setup pre-push hooks

* POC for githooks in windows

* modify pre-push for unix

* fix hooks for linux

* Add green color in echo

* test

* test

* test

* test

* Using diff to check

* remove change in elastic-san

* skip hooks when no modules

* Add pre-commit hooks

* Add README.md file

* Add success messages

* fix error message

* fix error message

* fix error message

* fix error message

* Update readme.md

* Update README.md

* Add echo for azdev scan

* Add echo when no module

* Update .githooks/azdev_active.sh

Co-authored-by: ZelinWang <[email protected]>

* Update .gitattributes

Co-authored-by: ZelinWang <[email protected]>

* Update .githooks/README.md

Co-authored-by: ZelinWang <[email protected]>

* Update .githooks/azdev_active.ps1

Co-authored-by: ZelinWang <[email protected]>

* Fix srt and tgt

* test

* test

* add echo in pre-commit for head

* Add code to check azure-cli and azure-cli-extension repo codes

* add extension repo verification

* Auto detect and add extensions

* fix issue in pre-push.sh

* fix issue in pre-push.sh

* test

* export tests in test_result.xml file

* ignore the output of test error stream

* remove test line

* remove the test_result.xml file if test success

* Add docs for .githooks

* test

* test

* use medium min-servity for azdev linter.

---------

Co-authored-by: ZelinWang <[email protected]>
  • Loading branch information
kairu-ms and wangzelin007 authored Nov 14, 2024
1 parent 8660356 commit fd0946c
Show file tree
Hide file tree
Showing 11 changed files with 568 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
# Set default behavior to automatically normalize line endings
* text=auto

# Force bash scripts to use LF
*.sh text eol=lf

# Force batch scripts to use CRLF
*.bat text eol=crlf

src/vmware/azext_vmware/tests/latest/recordings/*.yaml linguist-generated=true
57 changes: 57 additions & 0 deletions .githooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Git Hooks for Azure CLI Extension Development

## Setup

Please run the following command to enable the hooks.

```bash
azdev setup -c {azure_cli_repo_path} -r {azure_cli_extension_repo_path}

# if you install azdev which version is less than 0.1.84, you need to run the following command to enable the hooks
git config --local core.hooksPath .githooks
```

## Usage

Every time you git commit or git push, please make sure you have activated the python environment and completed the azdev setup.

If you want to skip the verification, you can add `--no-verify` to the git command.
This option will bypass any pre-commit or pre-push hooks that are configured in the repository, allowing you to commit or push changes without running these checks.
For example:
Skipping verification during commit
git commit -m "your commit message" --no-verify
Skipping verification during push
git push origin main --no-verify

## Note

### pre-commit

The pre-commit hook (`pre-commit.ps1`) performs the following checks:

1. Verifies that azdev is active in your current environment
2. Runs `azdev scan` on all staged files to detect potential secrets
3. If any secrets are detected, the commit will be blocked
- You can use `azdev mask` to remove secrets before committing
- Alternatively, use `git commit --no-verify` to bypass the check

### pre-push

The pre-push hooks (`pre-push.sh` for bash and `pre-push.ps1` for PowerShell) perform several quality checks:

1. Verifies that azdev is active in your current environment
2. Detects which repository you're working in:
- For azure-cli (when installed in editable mode):
* Checks if your branch needs rebasing against upstream/dev
* If rebasing is needed, displays instructions and provides a 5-second window to cancel
- For extensions:
* Automatically detects modified extensions
* Adds them to the test scope using `azdev extension add`
3. Runs the following quality checks on changed files:
- `azdev lint`: Checks for linting issues
- `azdev style`: Verifies code style compliance
- `azdev test`: Runs tests for modified code/extensions
4. If any check fails, the push will be blocked
- Use `git push --no-verify` to bypass these checks (not recommended)

The hooks support both Windows (PowerShell) and Unix-like systems (Bash), automatically using the appropriate script for your environment.
39 changes: 39 additions & 0 deletions .githooks/azdev_active.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Check if in the python environment
$pythonPath = (Get-Command python -ErrorAction SilentlyContinue).Path
Write-Host "PYTHON_PATH: $pythonPath"

if (-not $pythonPath) {
Write-Host "Error: Python not found in PATH" -ForegroundColor Red
exit 1
}

$pythonEnvFolder = Split-Path -Parent (Split-Path -Parent $pythonPath)
$pythonActiveFile = Join-Path $pythonEnvFolder "Scripts\activate.ps1"

if (-not (Test-Path $pythonActiveFile)) {
Write-Host "Python active file does not exist: $pythonActiveFile" -ForegroundColor Red
Write-Host "Error: Please activate the python environment first." -ForegroundColor Red
exit 1
}

# Construct the full path to the .azdev\env_config directory
$azdevEnvConfigFolder = Join-Path $env:USERPROFILE ".azdev\env_config"
Write-Host "AZDEV_ENV_CONFIG_FOLDER: $azdevEnvConfigFolder"

# Check if the directory exists
if (-not (Test-Path $azdevEnvConfigFolder)) {
Write-Host "AZDEV_ENV_CONFIG_FOLDER does not exist: $azdevEnvConfigFolder" -ForegroundColor Red
Write-Host "Error: azdev environment is not completed, please run 'azdev setup' first." -ForegroundColor Red
exit 1
}

$configFile = Join-Path $azdevEnvConfigFolder ($pythonEnvFolder.Substring(2) + "\config")
if (-not (Test-Path $configFile)) {
Write-Host "CONFIG_FILE does not exist: $configFile" -ForegroundColor Red
Write-Host "Error: azdev environment is not completed, please run 'azdev setup' first." -ForegroundColor Red
exit 1
}

Write-Host "CONFIG_FILE: $configFile"

exit 0
41 changes: 41 additions & 0 deletions .githooks/azdev_active.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/bash

# Check if in the python environment
PYTHON_FILE=$(which python)
printf "PYTHON_PATH: %s\n" "$PYTHON_FILE"

if [ -z "$PYTHON_FILE" ]; then
printf "\033[0;31mError: Python not found in PATH\033[0m\n"
exit 1
fi

PYTHON_ENV_FOLDER=$(dirname "$PYTHON_FILE")
PYTHON_ACTIVE_FILE="$PYTHON_ENV_FOLDER/activate"

if [ ! -f "$PYTHON_ACTIVE_FILE" ]; then
printf "Python active file does not exist: %s\n" "$PYTHON_ACTIVE_FILE"
printf "\033[0;31mError: Please activate the python environment first.\033[0m\n"
exit 1
fi

# Construct the full path to the .azdev/env_config directory
AZDEV_ENV_CONFIG_FOLDER="$HOME/.azdev/env_config"
printf "AZDEV_ENV_CONFIG_FOLDER: %s\n" "$AZDEV_ENV_CONFIG_FOLDER"

# Check if the directory exists
if [ ! -d "$AZDEV_ENV_CONFIG_FOLDER" ]; then
printf "AZDEV_ENV_CONFIG_FOLDER does not exist: %s\n" "$AZDEV_ENV_CONFIG_FOLDER"
printf "\033[0;31mError: azdev environment is not completed, please run 'azdev setup' first.\033[0m\n"
exit 1
fi

PYTHON_ENV_FOLDER=$(dirname "$PYTHON_ENV_FOLDER")

CONFIG_FILE="$AZDEV_ENV_CONFIG_FOLDER${PYTHON_ENV_FOLDER}/config"
if [ ! -f "$CONFIG_FILE" ]; then
printf "CONFIG_FILE does not exist: %s\n" "$CONFIG_FILE"
printf "\033[0;31mError: azdev environment is not completed, please run 'azdev setup' first.\033[0m\n"
exit 1
fi

printf "CONFIG_FILE: %s\n" "$CONFIG_FILE"
13 changes: 13 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env sh
":" //; if command -v pwsh >/dev/null 2>&1; then pwsh -ExecutionPolicy Bypass -File .githooks/pre-commit.ps1; else sh .githooks/pre-commit.sh; fi; exit $? # Try PowerShell Core first, then sh on Unix
":" //; exit # Skip rest on Unix

@echo off
powershell -NoProfile -Command "if (Get-Command powershell -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"
if %errorlevel% equ 0 (
powershell -ExecutionPolicy Bypass -File .githooks\pre-commit.ps1
) else (
echo Error: PowerShell is not available. Please install PowerShell.
exit /b 1
)
exit /b %errorlevel%
42 changes: 42 additions & 0 deletions .githooks/pre-commit.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env pwsh
Write-Host "Running pre-commit hook in powershell..." -ForegroundColor Green

# run azdev_active script
$scriptPath = Join-Path $PSScriptRoot "azdev_active.ps1"
. $scriptPath
if ($LASTEXITCODE -ne 0) {
exit 1
}

# Run command azdev scan
Write-Host "Running azdev scan..." -ForegroundColor Green

# Check if we have a previous commit to compare against
if (git rev-parse --verify HEAD 2>$null) {
Write-Host "Using HEAD as the previous commit"
$against = "HEAD"
}
else {
Write-Host "Using an empty tree object as the previous commit"
$against = $(git hash-object -t tree /dev/null)
}

$hasSecrets = 0
$files = $(git diff --cached --name-only --diff-filter=AM $against)

foreach ($file in $files) {
# Check if the file contains secrets
$detected = $(azdev scan -f $file | ConvertFrom-Json).secrets_detected
if ($detected -eq "True") {
Write-Host "Detected secrets from $file. You can run 'azdev mask' to remove secrets before commit." -ForegroundColor Red
$hasSecrets = 1
}
}

if ($hasSecrets -eq 1) {
Write-Host "Secret detected. If you want to skip that, run add '--no-verify' in the end of 'git commit' command." -ForegroundColor Red
exit 1
}

Write-Host "Pre-commit hook passed." -ForegroundColor Green
exit 0
38 changes: 38 additions & 0 deletions .githooks/pre-commit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash
printf "\033[0;32mRunning pre-commit hook in bash ...\033[0m\n"

# run azdev_active script
SCRIPT_PATH="$(dirname "$0")/azdev_active.sh"
. "$SCRIPT_PATH"
if [ $? -ne 0 ]; then
exit 1
fi

# Run command azdev scan
printf "\033[0;32mRunning azdev scan...\033[0m\n"

if git rev-parse --verify HEAD >/dev/null 2>&1
then
printf "Using HEAD as the previous commit\n"
against=HEAD
else
printf "Using an empty tree object as the previous commit\n"
against=$(git hash-object -t tree /dev/null)
fi
has_secrets=0
for FILE in `git diff --cached --name-only --diff-filter=AM $against` ; do
# Check if the file contains secrets
detected=$(azdev scan -f "$FILE" | python -c "import sys, json; print(json.load(sys.stdin)['secrets_detected'])")
if [ "$detected" = "True" ]; then
printf "\033[0;31mDetected secrets from %s, You can run 'azdev mask' to remove secrets before commit.\033[0m\n" "$FILE"
has_secrets=1
fi
done

if [ $has_secrets -eq 1 ]; then
printf "\033[0;31mSecret detected. If you want to skip that, run add '--no-verify' in the end of 'git commit' command.\033[0m\n"
exit 1
fi

printf "\033[0;32mPre-commit hook passed.\033[0m\n"
exit 0
13 changes: 13 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env sh
":" //; if command -v pwsh >/dev/null 2>&1; then pwsh -ExecutionPolicy Bypass -File .githooks/pre-push.ps1; else sh .githooks/pre-push.sh; fi; exit $? # Try PowerShell Core first, then sh on Unix
":" //; exit # Skip rest on Unix

@echo off
powershell -NoProfile -Command "if (Get-Command powershell -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"
if %errorlevel% equ 0 (
powershell -ExecutionPolicy Bypass -File .githooks\pre-push.ps1
) else (
echo Error: PowerShell is not available. Please install PowerShell.
exit /b 1
)
exit /b %errorlevel%
Loading

0 comments on commit fd0946c

Please sign in to comment.