Repository navigation
policy: make CodeRabbit review-only and block new Python in CI #307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c028225
52dfa43
b60216e
cba898a
d6b154a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # SPDX-License-Identifier: MPL-2.0 | ||
| # Review-only. No AI-authored finishing-touch commits. | ||
| # Canonical language policy: | ||
| # https://github.com/metadatastician/standards/blob/main/3-practice/LANGUAGE-POLICY.adoc | ||
| reviews: | ||
| auto_review: | ||
| enabled: true | ||
| drafts: false | ||
| path_instructions: | ||
| - path: "**/*" | ||
| instructions: >- | ||
| Estate policy prohibits NEW Python files, scripts, test code, | ||
| dependencies, and Python package manifests with no exceptions. | ||
| Do not recommend Python or generate Python fixes. The existing | ||
| upstream React and TypeScript frontend is temporarily permitted until | ||
| Marid is ready. Scientific code is Julia and R with pinned toolchains. | ||
| Flag additions of Python as a policy violation. Do not rewrite | ||
| unrelated upstream code for cosmetic compliance. Validate any | ||
| replacement through scientific result parity and tests. | ||
| finishing_touches: | ||
| docstrings: | ||
| enabled: false | ||
| unit_tests: | ||
| enabled: false | ||
| simplify: | ||
| enabled: false | ||
| autofix: | ||
| enabled: false | ||
| fix_ci: | ||
| enabled: false | ||
| resolve_merge_conflict: | ||
| enabled: false |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # SPDX-License-Identifier: MPL-2.0 | ||
| name: Language policy (no new Python) | ||
| on: | ||
| pull_request: | ||
| branches: [main] | ||
| push: | ||
| branches: [main] | ||
| workflow_dispatch: | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| no-new-python: | ||
| name: No new Python | ||
| runs-on: ubuntu-24.04 | ||
| timeout-minutes: 5 | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| fetch-depth: 0 | ||
| ref: ${{ github.event.pull_request.head.sha || github.sha }} | ||
| - name: Refuse Python additions and edits (allow deletion) | ||
| env: | ||
| PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} | ||
| PUSH_BEFORE_SHA: ${{ github.event.before }} | ||
| EVENT_KIND: ${{ github.event_name }} | ||
| run: | | ||
| set -euo pipefail | ||
| if [[ "$EVENT_KIND" == pull_request ]]; then | ||
| base=$PR_BASE_SHA | ||
| elif [[ "$EVENT_KIND" == push ]]; then | ||
| base=$PUSH_BEFORE_SHA | ||
| if [[ "$base" == 0000000000000000000000000000000000000000 ]]; then | ||
| echo 'No push base available: refusing ambiguous evidence' >&2 | ||
| exit 2 | ||
| fi | ||
| else | ||
| echo 'Manual probe covers HEAD^..HEAD, not PR merge-base scope' | ||
| base=$(git rev-parse HEAD^) | ||
| fi | ||
| bash scripts/check-no-new-python.sh "$base" | ||
| - name: Planted-negative and positive controls | ||
| run: bash scripts/tests/test-no-new-python.sh | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #!/usr/bin/env bash | ||
| # SPDX-License-Identifier: MPL-2.0 | ||
| # Refuse newly added/modified Python source and manifests. Untouched inherited | ||
| # debt is not a blanket authorisation to add more. Deletion is allowed. | ||
| set -euo pipefail | ||
| if [[ $# -ne 1 || ! "$1" =~ ^[0-9a-fA-F]{40}$ ]]; then | ||
| printf 'Usage: %s <base-commit-sha>\n' "$0" >&2 | ||
| exit 2 | ||
| fi | ||
| base=$1 | ||
| if ! git cat-file -e "${base}^{commit}"; then | ||
| echo 'Base commit unavailable; no language-policy evidence' >&2 | ||
| exit 2 | ||
| fi | ||
| changed=$(mktemp) | ||
| trap 'rm -f "$changed"' EXIT | ||
| if ! git diff --name-only --diff-filter=ACMR -z "${base}...HEAD" -- > "$changed"; then | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The Useful? React with 👍 / 👎. |
||
| echo 'Cannot determine changed files; refusing a false green' >&2 | ||
| exit 2 | ||
| fi | ||
| bad=0 | ||
| while IFS= read -r -d '' file; do | ||
| case "${file##*/}" in | ||
|
Check failure on line 23 in scripts/check-no-new-python.sh
|
||
| *.py|*.pyi|pyproject.toml|Pipfile|Pipfile.lock|poetry.lock|uv.lock|.python-version|setup.cfg|tox.ini|pytest.ini|requirements*.txt|requirements*.in) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The gate classifies files only by a small filename allowlist, so an executable such as Useful? React with 👍 / 👎. |
||
| printf 'BANNED Python contribution: %q\n' "$file" >&2 | ||
| bad=1 ;; | ||
| esac | ||
| done < "$changed" | ||
| if (( bad )); then | ||
| echo 'Python is banned for new work; migrate to approved languages. Removal-only cleanup is allowed.' >&2 | ||
| echo 'Canon: metadatastician/standards/3-practice/LANGUAGE-POLICY.adoc section 3' >&2 | ||
| exit 1 | ||
| fi | ||
| echo 'Language policy PASS: no new or modified Python files/manifests in this diff; legacy untouched files are not certified.' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| #!/usr/bin/env bash | ||
| # SPDX-License-Identifier: MPL-2.0 | ||
| # Both pass and planted-fail controls for the diff-based ban. | ||
| set -euo pipefail | ||
| script=$(cd "$(dirname "$0")/.." && pwd)/check-no-new-python.sh | ||
| scratch=$(mktemp -d) | ||
| trap 'rm -rf "$scratch"' EXIT | ||
| cd "$scratch" | ||
| git init -q | ||
| git config user.name 'Language Gate Test' | ||
| git config user.email 'language-gate@example.invalid' | ||
| mkdir -p bench scripts | ||
| printf 'print("legacy")\n' > scripts/legacy.py | ||
| git add . && git commit -qm 'Pre-existing Python debt' | ||
| base=$(git rev-parse HEAD) | ||
| expect_failure() { | ||
| if bash "$script" "$base" > "$scratch/output.log" 2>&1; then | ||
| echo 'ERROR: planted Python violation passed' >&2; exit 1 | ||
| fi | ||
| grep -q 'BANNED Python contribution:' "$scratch/output.log" || { cat "$scratch/output.log" >&2; exit 1; } | ||
| } | ||
| expect_pass() { bash "$script" "$base" > /dev/null; } | ||
| printf 'cat("R allowed")\n' > bench/check.R | ||
| git add . && git commit -qm 'Add R' | ||
| expect_pass | ||
| printf 'print("new")\n' > bench/new.py | ||
| git add . && git commit -qm 'Add Python' | ||
| expect_failure | ||
| git rm -q bench/new.py && git commit -qm 'Remove Python' | ||
| expect_pass | ||
| printf 'print("changed")\n' >> scripts/legacy.py | ||
| git add . && git commit -qm 'Edit legacy Python' | ||
| expect_failure | ||
| git restore --source="$base" scripts/legacy.py | ||
| git add . && git commit -qm 'Restore legacy' | ||
| expect_pass | ||
| printf '[project]\nname = "wrong"\n' > pyproject.toml | ||
| git add . && git commit -qm 'Add Python manifest' | ||
| expect_failure | ||
| git rm -q pyproject.toml && git commit -qm 'Remove manifest' | ||
| expect_pass | ||
| git rm -q scripts/legacy.py && git commit -qm 'Retire Python' | ||
| expect_pass | ||
| if bash "$script" not-a-sha >/dev/null 2>&1; then echo 'Malformed base passed' >&2; exit 1; fi | ||
| if bash "$script" 0000000000000000000000000000000000000000 >/dev/null 2>&1; then echo 'Missing base passed' >&2; exit 1; fi | ||
| echo 'no-new-python gate: planted-positive and planted-negative fixtures PASS' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For pull requests, the workflow checks out the contributor-controlled head SHA and then executes both policy scripts from that checkout. A PR can therefore add Python while modifying
scripts/check-no-new-python.shand its self-test to return success, making the requiredNo new Pythoncheck green; the enforcement logic should come from a trusted base revision or otherwise be protected from changes in the PR being evaluated.Useful? React with 👍 / 👎.