Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,20 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install black==24.8.0 isort==5.13.2
pip install black==24.8.0 isort==5.13.2 bandit[toml]

- name: Make Bandit helper executable
run: chmod +x scripts/linters/run_bandit.sh

- name: Run Black
run: black --check .

- name: Run Isort
run: isort --check-only .

- name: Run Bandit
run: ./scripts/linters/run_bandit.sh

# - name: Run Flake8
# run: flake8 .

Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ dist/
.pytest_cache
*.egg-info
.DS_Store
_version.py
_version.py
bandit-report.json
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[![PyPI](https://img.shields.io/pypi/v/arm-cli.svg)](https://pypi.org/project/arm-cli/)
[![Changelog](https://img.shields.io/github/v/release/mpowelson/arm-cli?include_prereleases&label=changelog)](https://github.com/mpowelson/arm-cli/releases)
[![Tests](https://github.com/mpowelson/arm-cli/actions/workflows/test.yml/badge.svg)](https://github.com/mpowelson/arm-cli/actions/workflows/test.yml)
[![CodeQL Analysis](https://github.com/mpowelson/arm-cli/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/mpowelson/arm-cli/actions/workflows/codeql-analysis.yml)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mpowelson/arm-cli/blob/master/LICENSE)

Experimental CLI for deploying robotic applications
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dev = [
"pytest",
"flake8",
"mypy",
"bandit[toml]",
]

[tool.setuptools]
Expand All @@ -54,9 +55,15 @@ target-version = ['py38']
profile = "black"
line_length = 100
multi_line_output = 3
extend_skip = ["arm_cli/_version.py"]

[tool.mypy]
python_version = "3.8"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true

[tool.bandit]
exclude_dirs = ["tests", "venv", ".venv", "env", ".env"]
skips = ["B101", "B601"]
targets = ["arm_cli"]
52 changes: 52 additions & 0 deletions scripts/linters/run_bandit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash
# run_bandit.sh - Runs Bandit and prints a summary, failing only on HIGH severity

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

bandit -r arm_cli/ -f json -o bandit-report.json || true

if [ -f bandit-report.json ]; then
python3 - <<'EOF'
import json, sys

with open("bandit-report.json") as f:
data = json.load(f)

high_issues = []
medium_issues = []
low_issues = []

for issue in data.get("results", []):
sev = issue.get("issue_severity", "").upper()
if sev == "HIGH":
high_issues.append(issue)
elif sev == "MEDIUM":
medium_issues.append(issue)
elif sev == "LOW":
low_issues.append(issue)

all_issues = high_issues + medium_issues + low_issues

if all_issues:
print("\033[1;33mBandit security summary:\033[0m")
for issue in all_issues:
sev = issue.get("issue_severity")
conf = issue.get("issue_confidence")
file = issue.get("filename")
line = issue.get("line_number")
text = issue.get("issue_text")
print(f"[{sev}/{conf}] {file}:{line} {text}")
print("")

if high_issues:
print(f"\033[0;31mFound {len(high_issues)} HIGH severity issues - failing!\033[0m")
sys.exit(1)
else:
print("\033[0;32mNo HIGH severity issues found.\033[0m")
EOF
fi
52 changes: 40 additions & 12 deletions scripts/run_linters.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,30 @@ fi
print_status "Starting linting checks for arm-cli..."
print_status "Ensuring required tools are installed..."
python -m pip install --upgrade pip >/dev/null
python -m pip install black==24.8.0 isort==5.13.2 >/dev/null
python -m pip install black==24.8.0 isort==5.13.2 bandit[toml] >/dev/null

# Run Black (code formatter)
print_status "Running Black (code formatter)..."
if black --check .; then
print_success "Black check passed - code is properly formatted"
BLACK_STATUS="PASSED"
else
print_error "Black check failed - code needs formatting"
print_status "Run 'black .' to automatically format the code"
BLACK_FAILED=true
BLACK_STATUS="FAILED"
fi

# Run isort (import sorter)
print_status "Running isort (import sorter)..."
if isort --check-only .; then
print_success "isort check passed - imports are properly sorted"
ISORT_STATUS="PASSED"
else
print_error "isort check failed - imports need sorting"
print_status "Run 'isort .' to automatically sort imports"
ISORT_FAILED=true
ISORT_STATUS="FAILED"
fi

# # Run Flake8 (style checker)
Expand All @@ -69,6 +73,18 @@ fi
# FLAKE8_FAILED=true
# fi

# Run Bandit (security checker)
print_status "Running Bandit (security checker)..."
if ./scripts/linters/run_bandit.sh; then
print_success "Bandit check passed!"
BANDIT_STATUS="PASSED"
else
print_error "Bandit found HIGH severity issues!"
BANDIT_FAILED=true
BANDIT_STATUS="FAILED"
fi


# # Run MyPy (type checker)
# print_status "Running MyPy (type checker)..."
# if mypy .; then
Expand All @@ -81,17 +97,29 @@ fi
# Summary
echo
print_status "Linting Summary:"
if [ "$BLACK_FAILED" = true ] || [ "$ISORT_FAILED" = true ] || [ "$FLAKE8_FAILED" = true ] || [ "$MYPY_FAILED" = true ]; then
print_error "Some linting checks failed!"
echo
print_status "To fix formatting issues:"
echo " black ."
echo " isort ."
echo
print_status "To run individual linters:"
echo " flake8 ."
echo " mypy ."

# Black summary
echo "- Black: ${BLACK_STATUS:-SKIPPED}"
if [ "$BLACK_STATUS" = "FAILED" ]; then
echo " run: black ."
fi

# isort summary
echo "- isort: ${ISORT_STATUS:-SKIPPED}"
if [ "$ISORT_STATUS" = "FAILED" ]; then
echo " run: isort ."
fi

# Bandit summary
echo "- Bandit: ${BANDIT_STATUS:-SKIPPED}"
if [ "$BANDIT_STATUS" = "FAILED" ]; then
echo " run: ./scripts/linters/run_bandit.sh"
fi

# Final result
if [ "$BLACK_FAILED" = true ] || [ "$ISORT_FAILED" = true ] || [ "$BANDIT_FAILED" = true ]; then
print_error "One or more checks failed. See above for commands to rerun failed linters."
exit 1
else
print_success "All linting checks passed! 🎉"
fi
fi