forked from Azure/azure-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
{CI} Add git hooks support (Azure#30297)
* add githooks * fix src and tgt * Add rebase check * add rebase check * Add rebase upstream/dev warning. * Using merge base as target * test * print the warning again * +x for hooks * Replace echo with printf * fix printf * remove line for test * Improve the code for tests * Add docs for .githooks * use medium min-servity for azdev linter.
- Loading branch information
1 parent
b8c6e62
commit 6922859
Showing
10 changed files
with
464 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# 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. | ||
|
||
## 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. Confirms azure-cli is installed in editable mode | ||
3. Checks if your branch needs rebasing against upstream/dev | ||
- If rebasing is needed, displays instructions and provides a 5-second window to cancel | ||
4. 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 | ||
5. 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#!/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 { | ||
# Initial commit: diff against an empty tree object | ||
Write-Host "Using 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
Write-Host "Running pre-push hook in powershell..." -ForegroundColor Green | ||
|
||
# run azdev_active script and capture its output | ||
$scriptPath = Join-Path $PSScriptRoot "azdev_active.ps1" | ||
. $scriptPath | ||
if ($LASTEXITCODE -ne 0) { | ||
exit 1 | ||
} | ||
|
||
# Check if azure-cli is installed in editable mode | ||
$pipShowOutput = pip show azure-cli 2>&1 | ||
$editableLocation = if ($pipShowOutput) { | ||
$match = $pipShowOutput | Select-String "Editable project location: (.+)" | ||
if ($match) { | ||
$match.Matches.Groups[1].Value | ||
} | ||
} | ||
if ($editableLocation) { | ||
# get the parent of parent directory of the editable location | ||
$AZURE_CLI_FOLDER = Split-Path -Parent (Split-Path -Parent $editableLocation) | ||
} else { | ||
Write-Host "Error: azure-cli is not installed in editable mode. Please install it in editable mode using `azdev setup`." -ForegroundColor Red | ||
exit 1 | ||
} | ||
|
||
# Get extension repo paths and join them with spaces | ||
$Extensions = (azdev extension repo list -o tsv) -join ' ' | ||
|
||
# Fetch upstream/dev branch | ||
Write-Host "Fetching upstream/dev branch..." -ForegroundColor Green | ||
git fetch upstream dev | ||
if ($LASTEXITCODE -ne 0) { | ||
Write-Host "Error: Failed to fetch upstream/dev branch. Please run 'git remote add upstream https://github.com/Azure/azure-cli.git' first." -ForegroundColor Red | ||
exit 1 | ||
} | ||
|
||
# Check if current branch needs rebasing | ||
$mergeBase = git merge-base HEAD upstream/dev | ||
$upstreamHead = git rev-parse upstream/dev | ||
if ($mergeBase -ne $upstreamHead) { | ||
Write-Host "" | ||
Write-Host "Your branch is not up to date with upstream/dev. Please run the following commands to rebase and setup:" -ForegroundColor Yellow | ||
Write-Host "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" -ForegroundColor Yellow | ||
Write-Host "git rebase upstream/dev" -ForegroundColor Yellow | ||
if ($Extensions) { | ||
Write-Host "azdev setup -c $AZURE_CLI_FOLDER -r $Extensions" -ForegroundColor Yellow | ||
} else { | ||
Write-Host "azdev setup -c $AZURE_CLI_FOLDER" -ForegroundColor Yellow | ||
} | ||
Write-Host "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" -ForegroundColor Yellow | ||
Write-Host "" | ||
Write-Host "You have 5 seconds to stop the push (Ctrl+C)..." -ForegroundColor Yellow | ||
for ($i = 5; $i -gt 0; $i--) { | ||
Write-Host "`rTime remaining: $i seconds..." -NoNewline -ForegroundColor Yellow | ||
Start-Sleep -Seconds 1 | ||
} | ||
Write-Host "`rContinuing without rebase..." | ||
} | ||
|
||
# get the current branch name | ||
$currentBranch = git branch --show-current | ||
|
||
# Run command azdev lint | ||
Write-Host "Running azdev lint..." -ForegroundColor Green | ||
azdev linter --min-severity medium --repo ./ --src $currentBranch --tgt $mergeBase | ||
if ($LASTEXITCODE -ne 0) { | ||
Write-Host "Error: azdev lint check failed." -ForegroundColor Red | ||
exit 1 | ||
} | ||
|
||
# Run command azdev style | ||
Write-Host "Running azdev style..." -ForegroundColor Green | ||
azdev style --repo ./ --src $currentBranch --tgt $mergeBase | ||
if ($LASTEXITCODE -ne 0) { | ||
$error_msg = azdev style --repo ./ --src $currentBranch --tgt $mergeBase 2>&1 | ||
if ($error_msg -like "*No modules*") { | ||
Write-Host "Pre-push hook passed." -ForegroundColor Green | ||
exit 0 | ||
} | ||
Write-Host "Error: azdev style check failed." -ForegroundColor Red | ||
exit 1 | ||
} | ||
|
||
# Run command azdev test | ||
Write-Host "Running azdev test..." -ForegroundColor Green | ||
azdev test --repo ./ --src $currentBranch --tgt $mergeBase --discover --no-exitfirst --xml-path test_results.xml 2>$null | ||
if ($LASTEXITCODE -ne 0) { | ||
Write-Host "Error: azdev test check failed." -ForegroundColor Red | ||
exit 1 | ||
} else { | ||
# remove test_results.xml file | ||
Remove-Item test_results.xml | ||
} | ||
|
||
Write-Host "Pre-push hook passed." -ForegroundColor Green | ||
|
||
if ($mergeBase -ne $upstreamHead) { | ||
Write-Host "" | ||
Write-Host "Your branch is not up to date with upstream/dev. Please run the following commands to rebase code and setup:" -ForegroundColor Yellow | ||
Write-Host "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" -ForegroundColor Yellow | ||
Write-Host "git rebase upstream/dev" -ForegroundColor Yellow | ||
if ($Extensions) { | ||
Write-Host "azdev setup -c $AZURE_CLI_FOLDER -r $Extensions" -ForegroundColor Yellow | ||
} else { | ||
Write-Host "azdev setup -c $AZURE_CLI_FOLDER" -ForegroundColor Yellow | ||
} | ||
Write-Host "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" -ForegroundColor Yellow | ||
} | ||
exit 0 |
Oops, something went wrong.