diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d189a503397..57a19ab0073 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,5 +18,5 @@ Before opening a pull request, developer should: 7. select the _Allow edits from maintainers_ option (see this [article](https://help.github.com/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork/) for more details). After opening a pull request, developer: - - should create a new small markdown log file using the PR number e.g. `1010_fix.md` or `1010_add.md` inside `draftlogs` folder as described in this [README](https://github.com/plotly/plotly.js/blob/master/draftlogs/README.md), commit it and push. + - should create a new small markdown log file using the PR number e.g. `1010_fix.md` or `1010_add.md` inside `draftlogs` folder as described in this [README](https://github.com/plotly/plotly.js/blob/master/draftlogs/README.md), commit it and push. A CI check enforces this; PRs that don't warrant a CHANGELOG entry can opt out by applying the `no-draftlog` label. - should **not** force push (i.e. `git push -f`) to remote branches associated with opened pull requests. Force pushes make it hard for maintainers to keep track of updates. Therefore, if required, please fetch `upstream/master` and "merge" with master instead of "rebase". diff --git a/.github/workflows/check-draftlog.yml b/.github/workflows/check-draftlog.yml new file mode 100644 index 00000000000..c957ced2e78 --- /dev/null +++ b/.github/workflows/check-draftlog.yml @@ -0,0 +1,77 @@ +name: Check Draftlog + +on: + pull_request: + types: [opened, reopened, synchronize, labeled, unlabeled, ready_for_review] + +concurrency: + group: check-draftlog-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + check-draftlog: + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 0 + + - name: Check for a new draftlog entry + env: + PR_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + set -euo pipefail + + if echo "$PR_LABELS" | grep -q '"no-draftlog"'; then + echo "Skipping draftlog check: 'no-draftlog' label is set." + exit 0 + fi + + ADDED=$(git diff --name-only --diff-filter=A "$BASE_SHA"...HEAD -- 'draftlogs/*.md' | grep -v '^draftlogs/README\.md$' || true) + + if [ -z "$ADDED" ]; then + echo "::error::No new draftlog entry was added under draftlogs/." + echo "" + echo "Most PRs should add a markdown file under draftlogs/ for the next CHANGELOG." + echo "See draftlogs/README.md for the filename convention." + echo "" + echo "If this PR genuinely does not need a changelog entry (e.g. CI-only," + echo "internal refactor, docs typo), add the 'no-draftlog' label to this PR." + exit 1 + fi + + INVALID_NAMES=$(echo "$ADDED" | grep -vE '^draftlogs/[0-9]+_(fix|add|remove|change|deprecate)\.md$' || true) + if [ -n "$INVALID_NAMES" ]; then + echo "::error::Invalid draftlog filename(s):" + echo "$INVALID_NAMES" | sed 's/^/ - /' + echo "" + echo "Expected pattern: draftlogs/_(fix|add|remove|change|deprecate).md" + echo "See draftlogs/README.md for details." + exit 1 + fi + + MISSING_LINK="" + while IFS= read -r f; do + [ -z "$f" ] && continue + if ! grep -qE '\[\[#[0-9]+\]\(https://github\.com/plotly/plotly\.js/pull/[0-9]+\)\]' "$f"; then + MISSING_LINK="$MISSING_LINK$f"$'\n' + fi + done <<< "$ADDED" + + if [ -n "$MISSING_LINK" ]; then + echo "::error::Draftlog entry(ies) missing a PR link:" + printf '%s' "$MISSING_LINK" | sed 's/^/ - /' + echo "" + echo "Each entry must include a link in the form:" + echo " [[#1234](https://github.com/plotly/plotly.js/pull/1234)]" + echo "See draftlogs/README.md for an example." + exit 1 + fi + + echo "Found new draftlog entry(ies):" + echo "$ADDED" | sed 's/^/ - /' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 43dc2d31f8c..76d8f962e0b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,6 +71,7 @@ We use the following [labels](https://github.com/plotly/plotly.js/labels) to tra | `status: in progress` | PRs that required some initial feedback but not ready to merge | | `status: reviewable` | PRs that are completed from the author's perspective | | `status: on hold` | PRs that are put on hold | +| `no-draftlog` | PR opted out of the [draftlog](./draftlogs/README.md) check | ## Development diff --git a/draftlogs/README.md b/draftlogs/README.md index 5ae928cb0cc..88ec158e566 100644 --- a/draftlogs/README.md +++ b/draftlogs/README.md @@ -19,4 +19,15 @@ If your PR falls into more than one category - for example adding a new feature which would render - Add `icicle` trace type [[#5546](https://github.com/plotly/plotly.js/pull/5546)] -> Please start your single-line or multiple lined message with a verb. You could basically use the PR description while providing a link to the PR similar to the above example is appreciated too. +> Please start your single-line or multiple lined message with a verb. + +Each entry must include a link back to the PR in the form shown above: +`[[#1234](https://github.com/plotly/plotly.js/pull/1234)]` (a link to +`/issues/1234` is also accepted, since GitHub redirects between the two). + +### Skipping the draftlog + +A CI check enforces that every pull request adds a new file under +`draftlogs/`. If your PR genuinely does not warrant a CHANGELOG entry +(e.g. a CI-only change, internal refactor, or docs typo), add the +`no-draftlog` label to the PR to opt out.