mirror of
https://github.com/kuhyx/diet-guard.git
synced 2026-11-10 17:47:20 +01:00
repo contract: CLAUDE.md commands, test_changed, CI gate
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (mypy, mypy, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (pylint, pylint, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (rest, , mypy,pylint) (push) Waiting to run
Tests / test (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (mypy, mypy, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (pylint, pylint, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (rest, , mypy,pylint) (push) Waiting to run
Tests / test (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bf35afbdf5
commit
f0623d0c44
25
.github/workflows/repo-contract.yml
vendored
Normal file
25
.github/workflows/repo-contract.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: repo-contract
|
||||
|
||||
# The local pre-commit hook can be skipped (a fresh clone has no hooks), so the
|
||||
# contract is enforced on push too. Mirrors md-naming.yml.
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
repo-contract:
|
||||
name: repo contract
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Check out the shared gate
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: kuhyx/utils
|
||||
path: .utils
|
||||
|
||||
- name: Enforce the repo contract
|
||||
run: bash .utils/scripts/check_repo_contract.sh
|
||||
@ -249,3 +249,9 @@ repos:
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
stages: [pre-push]
|
||||
- id: repo-contract
|
||||
name: repo contract (CLAUDE.md Commands + test_changed)
|
||||
entry: scripts/check_repo_contract.sh
|
||||
language: system
|
||||
pass_filenames: false
|
||||
files: ^(CLAUDE\.md|AGENTS\.md|scripts/test_changed\.sh)$
|
||||
|
||||
15
AGENTS.md
15
AGENTS.md
@ -16,17 +16,16 @@ catch-up rule).
|
||||
|
||||
## Commands
|
||||
|
||||
- Tests: `python -m pytest diet_guard/tests/ --cov=diet_guard --cov-branch --cov-fail-under=100`
|
||||
- Lint: `pre-commit run --all-files`
|
||||
- Test the lock (safe, closeable): `python -m diet_guard gate --demo`
|
||||
- One sync tick: `python -m diet_guard sync`
|
||||
- Averages: `python -m diet_guard averages`; Body: `body`, `weight KG`, `profile`, `plan-week`
|
||||
- Prune dead sync peers (dry run): `python -m diet_guard prune-peers`
|
||||
- Install for production: `bash install.sh`
|
||||
- App tests: `cd app && flutter test`
|
||||
- Desktop app: `cd app && bash run.sh`
|
||||
- Install desktop app: `cd app && bash install_arch.sh`
|
||||
- Phone build: `cd app && flutter build apk --release`
|
||||
- Install: `bash install.sh` (production); app: `cd app && bash install_arch.sh`; run app: `bash run.sh`; phone: `flutter build apk --release`
|
||||
- run: `python -m diet_guard gate --demo`
|
||||
- test: `python -m pytest -n auto -p no:sugar -q` (python, 100% branch bar from pyproject) then `cd app && flutter test --reporter=compact`
|
||||
- test-changed: `scripts/test_changed.sh` (maps py and app/ dart changes to their tests, no coverage)
|
||||
- lint: `pre-commit run --all-files`
|
||||
- coverage: `python -m pytest -n auto -p no:sugar -q` (writes coverage.lcov)
|
||||
- coverage-gaps: `coverage-gaps coverage.lcov`
|
||||
|
||||
## Scheduling
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ name: diet_guard_app
|
||||
description: "Companion phone app for diet_guard: log meals on the go."
|
||||
publish_to: 'none'
|
||||
|
||||
version: 1.0.99+1
|
||||
version: 1.0.100+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.12.2
|
||||
|
||||
26
scripts/check_repo_contract.sh
Executable file
26
scripts/check_repo_contract.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ============================================================================
|
||||
# Fail if this repo breaks the shared repo contract.
|
||||
#
|
||||
# Thin delegate to the shared gate in ~/src/utils, which owns the contract
|
||||
# text. Copy this file to scripts/check_repo_contract.sh in a repo; never copy
|
||||
# the shared gate itself, or the shim would exec itself forever.
|
||||
# ============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly SHARED_GATE="${UTILS_ROOT:-$HOME/src/utils}/scripts/check_repo_contract.sh"
|
||||
|
||||
main() {
|
||||
if [[ ! -x "$SHARED_GATE" ]]; then
|
||||
echo "Error: shared repo-contract gate not found at $SHARED_GATE" >&2
|
||||
echo " Clone github.com/kuhyx/utils to ~/src/utils, or set" >&2
|
||||
echo " UTILS_ROOT to where it lives." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec bash "$SHARED_GATE" "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
72
scripts/test_changed.sh
Executable file
72
scripts/test_changed.sh
Executable file
@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ============================================================================
|
||||
# Run only the tests related to files changed vs HEAD (staged, unstaged and
|
||||
# untracked). Quiet: failures plus a one-line summary. Falls back to the full
|
||||
# suite when a change cannot be mapped to tests. Generated by repo_contract.
|
||||
# ============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
CHANGED=()
|
||||
while IFS= read -r f; do
|
||||
[[ -n "$f" && -e "$f" ]] && CHANGED+=("$f")
|
||||
done < <({ git diff --name-only HEAD 2>/dev/null || true; git ls-files --others --exclude-standard; } | sort -u)
|
||||
|
||||
# --no-cov: a subset cannot meet the 100% bar, and the term-missing table is noise.
|
||||
pytest_run() {
|
||||
local py=python3
|
||||
[[ -x .venv/bin/python ]] && py=.venv/bin/python
|
||||
"$py" -m pytest --no-cov -p no:sugar "$@"
|
||||
}
|
||||
|
||||
# Dart changes map to app/test/<name>_test.dart; any other app/ change runs the app suite.
|
||||
flutter_run() {
|
||||
(cd app && flutter test --reporter=compact "$@")
|
||||
}
|
||||
|
||||
if grep -qs testmon pyproject.toml requirements*.txt; then
|
||||
pytest_run --testmon -q --tb=short; exit $?
|
||||
fi
|
||||
|
||||
full=0
|
||||
tests=()
|
||||
dart_tests=()
|
||||
dart_full=0
|
||||
for f in "${CHANGED[@]}"; do
|
||||
case "$f" in
|
||||
*/conftest.py | conftest.py | pyproject.toml | requirements*.txt | pytest.ini | setup.cfg) full=1 ;;
|
||||
app/test/*_test.dart) dart_tests+=("${f#app/}") ;;
|
||||
app/lib/*.dart)
|
||||
base="$(basename "$f" .dart)"
|
||||
while IFS= read -r t; do dart_tests+=("${t#app/}"); done \
|
||||
< <(git ls-files "app/test/*${base}_test.dart")
|
||||
[[ ${#dart_tests[@]} -eq 0 ]] && dart_full=1
|
||||
;;
|
||||
app/pubspec.yaml | app/pubspec.lock) dart_full=1 ;;
|
||||
*.py)
|
||||
base="$(basename "$f" .py)"
|
||||
if [[ "$base" == test_* || "$base" == *_test ]]; then
|
||||
tests+=("$f")
|
||||
else
|
||||
while IFS= read -r t; do tests+=("$t"); done \
|
||||
< <(git ls-files "*test_${base}.py" "*${base}_test.py")
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ${#CHANGED[@]} -eq 0 ]]; then echo "no changes vs HEAD: nothing to test"; exit 0; fi
|
||||
rc=0
|
||||
if [[ $dart_full -eq 1 ]]; then flutter_run || rc=1
|
||||
elif [[ ${#dart_tests[@]} -gt 0 ]]; then flutter_run "${dart_tests[@]}" || rc=1; fi
|
||||
if [[ $full -eq 1 ]]; then
|
||||
echo "config changed: running full python suite"; pytest_run -q -n auto || rc=1
|
||||
elif [[ ${#tests[@]} -gt 0 ]]; then pytest_run -q --tb=short "${tests[@]}" || rc=1
|
||||
elif printf '%s\n' "${CHANGED[@]}" | grep -q '\.py$'; then
|
||||
echo "no mapped python tests: running full python suite"; pytest_run -q -n auto --tb=short || rc=1
|
||||
elif [[ $dart_full -eq 0 && ${#dart_tests[@]} -eq 0 ]]; then
|
||||
echo "no python/dart changes: nothing to test"
|
||||
fi
|
||||
exit "$rc"
|
||||
Loading…
Reference in New Issue
Block a user