#!/usr/bin/env bash
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
set -euo pipefail
TOP_DIR=$(git rev-parse --show-toplevel)
# shellcheck disable=SC2034
GO_DIR="${TOP_DIR}/go" # Reserved for future Go linting
PY_DIR="${TOP_DIR}/py"
# shellcheck disable=SC2034
JS_DIR="${TOP_DIR}/js" # Reserved for future JS linting
uv run --directory "${PY_DIR}" ruff check --fix --preview --unsafe-fixes .
uv run --directory "${PY_DIR}" ruff format --preview .
# Check lockfile is up to date
echo "--- π Checking lockfile is up to date ---"
uv lock --check --directory "${PY_DIR}"
# Fast type checkers first (blocking)
# Note: ty reads its config (environment.root) from py/pyproject.toml
echo "--- π Running Ty Type Check ---"
uv run --directory "${PY_DIR}" ty check .
# Pyrefly checks the full workspace (config in pyproject.toml handles PEP 420 namespace packages)
echo "--- π Running Pyrefly Type Check ---"
uv run --directory "${PY_DIR}" pyrefly check .
# Pyright runs on packages/ only (blocking)
echo "--- π Running Pyright Type Check ---"
uv run --directory "${PY_DIR}" pyright packages/
"${PY_DIR}/bin/run_python_security_checks"
# License checks
echo "--- π Running License Check ---"
"${TOP_DIR}/bin/check_license"
# Dependency license check
echo "--- π Running Dependency License Check ---"
uv run --directory "${PY_DIR}" liccheck -s pyproject.toml
# Consistency checks (Python versions, plugin versions, naming, workspace completeness)
echo "--- π Running Consistency Checks ---"
"${PY_DIR}/bin/check_consistency"
# Shell script linting
echo "--- π Running Shell Script Lint (shellcheck) ---"
if command -v shellcheck &> /dev/null; then
shell_errors=0
# Collect all shell scripts to check:
# 1. bin/* and py/bin/* (scripts without extensions)
# 2. All *.sh files in py/samples/ (run.sh, deploy_*.sh, test_*.sh, etc.)
shell_scripts=()
# bin/ scripts (detect by file type since they have no extension).
for script in "${TOP_DIR}"/bin/* "${PY_DIR}"/bin/*; do
if [ -f "$script" ] && file "$script" | grep -qE "shell|bash|sh script" 2>/dev/null; then
script_name=$(basename "$script")
# Skip .py files
if [[ "$script_name" == *.py ]]; then
continue
fi
shell_scripts+=("$script")
fi
done
# py/samples/ shell scripts (find all .sh files recursively).
while IFS= read -r -d '' script; do
shell_scripts+=("$script")
done < <(find "${PY_DIR}/samples" -name '*.sh' -type f -print0 2>/dev/null)
for script in "${shell_scripts[@]}"; do
# -x follows sourced files; -e SC1091 skips "not following" warnings
# for files like _common.sh that live in parent directories.
if ! shellcheck -x -e SC1091 "$script" 2>&1; then
shell_errors=$((shell_errors + 1))
fi
done
if [ $shell_errors -gt 0 ]; then
echo "β οΈ $shell_errors shell script(s) have shellcheck warnings"
exit 1
else
echo "β
All ${#shell_scripts[@]} shell scripts pass shellcheck"
fi
else
echo "β οΈ shellcheck not installed (brew install shellcheck) - skipping"
fi
# Disabled because there are many lint errors.
#pushd "${GO_DIR}" &>/dev/null
#golangci-lint run ./...
#go vet -v ./...
#popd &>/dev/null
#pnpm run -C ${JS_DIR} lint