diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7876211..c939166 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,20 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + credit-guard: + name: Changelog and contributor credit (issue #113) + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + with: + fetch-depth: 0 + - name: Check CHANGELOG.md and CONTRIBUTORS.md updates + env: + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: bash scripts/check_credit.sh "$BASE_SHA" "$HEAD_SHA" "$PR_AUTHOR" lint: name: Lint and type check runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b4a735..2258e26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) ## [Unreleased] +### Added +- `credit-guard` CI job: pull requests touching `philanthropy/` must also + update this changelog, and the author must be credited in + CONTRIBUTORS.md. Implemented as `scripts/check_credit.sh`, wired into + `ci.yml` on `pull_request` events only; failures surface as inline + `::error::` annotations on the Files tab. Closes #113. ### Fixed - `CRMCleaner.transform` no longer silently corrupts complex amounts into wrong finite floats: cells holding actual `complex` values are masked to diff --git a/scripts/check_credit.sh b/scripts/check_credit.sh new file mode 100755 index 0000000..2a72d33 --- /dev/null +++ b/scripts/check_credit.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Credit guard (issue #113): a PR that changes code under philanthropy/ must +# also touch CHANGELOG.md, and its author must already be credited in +# CONTRIBUTORS.md. Runs on pull_request events only; direct pushes to main +# and history that predates the guard are not checked. +set -euo pipefail + +base=$1 +head=$2 +author=${3:-} + +changed=$(git diff --name-only "$base" "$head") + +if ! echo "$changed" | grep -q '^philanthropy/'; then + echo "credit guard: no source changes under philanthropy/ - nothing to check" + exit 0 +fi + +if ! echo "$changed" | grep -qx 'CHANGELOG.md'; then + echo "::error::This PR touches files under philanthropy/ but not CHANGELOG.md. Add a line under [Unreleased] describing the change." + exit 1 +fi + +if [ -z "$author" ]; then + echo "::error::PR author could not be determined; cannot run the CONTRIBUTORS.md check." + exit 1 +fi + +# Match the literal token "@" not followed by another login character. +# The author is interpolated literally (awk index, no regex), so bot logins +# such as dependabot[bot] are not misread as a character class. +if ! awk -v token="@$author" ' + index($0, token) { + rest = substr($0, index($0, token) + length(token)) + if (rest == "" || rest !~ /^[A-Za-z0-9_-]/) { found = 1; exit } + } + END { exit found ? 0 : 1 } +' CONTRIBUTORS.md; then + echo "::error::This PR touches files under philanthropy/ but its author (@$author) is not listed in CONTRIBUTORS.md. Add yourself in the same pull request (see 'Getting listed')." + exit 1 +fi + +echo "credit guard OK: changelog touched and @$author is credited"