From 7c5f5f8365a23a874b2c4e0cea0b24b34c1a294e Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Tue, 28 Apr 2026 10:08:06 +0100 Subject: [PATCH] Implement PR-number-based proposal workflow This change simplifies the proposal numbering system by using PR numbers as proposal identifiers, eliminating number collisions and removing the need for a separate allocation process. Changes: - Simplified proposals/README.md to focus on author workflow - Removed index tables (directory listing serves as the index) - Streamlined instructions for creating and renaming proposals - Updated proposal template with workflow instructions - Require PR number in title format: # - - Moved workflow instructions into comment block - Added GitHub workflow to automatically check proposal numbering - Validates both filename and title format - Updates PR description when proposal files don't match PR number - Provides exact commands to fix naming issues - Removes warning once corrected - Handles both added and renamed files - Runs on all PRs (ready for mandatory status check) - Added notification script for existing open PRs - After merge, run notify-open-prs.sh to ask authors to rebase - Workflow will automatically guide them through renaming - Updated with all current open proposal PRs (#70, #82, #83, #85, #88, #93, #94, #96, #98, #99, #100, #101, #103) Proposals 001-019 retain their original numbers. Assisted-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: Keith Wall <kwall@apache.org> --- .github/workflows/proposal-numbering.yml | 209 +++++++++++++++++++++++ notify-open-prs.sh | 45 +++++ proposals/000-template.md | 19 ++- proposals/README.md | 39 +++++ 4 files changed, 309 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/proposal-numbering.yml create mode 100755 notify-open-prs.sh create mode 100644 proposals/README.md diff --git a/.github/workflows/proposal-numbering.yml b/.github/workflows/proposal-numbering.yml new file mode 100644 index 0000000..5de7e9c --- /dev/null +++ b/.github/workflows/proposal-numbering.yml @@ -0,0 +1,209 @@ +# +# Copyright Kroxylicious Authors. +# +# Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 +# + +# Automatically checks that proposal files follow the PR-number naming convention (e.g., proposals/092-my-proposal.md for PR #92). +# When a proposal file doesn't match its PR number, this workflow updates the PR description with instructions to rename it. +# Once the author fixes the naming, the warning is automatically removed from the PR description. + +name: Check Proposal Numbering + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + pull-requests: write + contents: read + +jobs: + check-numbering: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + fetch-depth: 0 + + - name: Check proposal file numbering + id: check + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + # Find all .md files directly in proposals directory (not subdirectories) + # Include both Added (A) and Renamed (R) files + ALL_PROPOSAL_FILES=$(git diff --name-only --diff-filter=AR origin/${{ github.base_ref }}...HEAD | grep '^proposals/[^/]*\.md$' || true) + + # Filter out non-proposal files (README.md and template) + PROPOSAL_FILES="" + for file in $ALL_PROPOSAL_FILES; do + # Skip README.md and the template + if [[ "$file" == "proposals/README.md" ]] || [[ "$file" == "proposals/000-template.md" ]]; then + continue + fi + PROPOSAL_FILES="$PROPOSAL_FILES $file" + done + + if [ -z "$PROPOSAL_FILES" ]; then + echo "No proposal files found in this PR" + echo "has_proposal=false" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "has_proposal=true" >> $GITHUB_OUTPUT + + # Expected filename pattern: proposals/0{PR_NUMBER}-*.md + EXPECTED_PREFIX=$(printf "proposals/%03d-" $PR_NUMBER) + + INCORRECT_FILES="" + INCORRECT_TITLES="" + for file in $PROPOSAL_FILES; do + # Check filename + if [[ ! "$file" =~ ^${EXPECTED_PREFIX} ]]; then + if [ -z "$INCORRECT_FILES" ]; then + INCORRECT_FILES="$file" + else + INCORRECT_FILES="$INCORRECT_FILES,$file" + fi + fi + + # Check title format (should be: # <PR_NUMBER> - <Title>) + EXPECTED_TITLE_PREFIX="# $PR_NUMBER -" + if ! grep -q "^${EXPECTED_TITLE_PREFIX}" "$file"; then + if [ -z "$INCORRECT_TITLES" ]; then + INCORRECT_TITLES="$file" + else + INCORRECT_TITLES="$INCORRECT_TITLES,$file" + fi + fi + done + + if [ -n "$INCORRECT_FILES" ] || [ -n "$INCORRECT_TITLES" ]; then + echo "incorrect=true" >> $GITHUB_OUTPUT + echo "files=$INCORRECT_FILES" >> $GITHUB_OUTPUT + echo "titles=$INCORRECT_TITLES" >> $GITHUB_OUTPUT + echo "expected_prefix=$EXPECTED_PREFIX" >> $GITHUB_OUTPUT + else + echo "incorrect=false" >> $GITHUB_OUTPUT + fi + + - name: Update PR description if numbering is incorrect + if: steps.check.outputs.incorrect == 'true' + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 + with: + script: | + const prNumber = context.payload.pull_request.number; + const expectedPrefix = '${{ steps.check.outputs.expected_prefix }}'; + const incorrectFilesRaw = '${{ steps.check.outputs.files }}'; + const incorrectTitlesRaw = '${{ steps.check.outputs.titles }}'; + + const warnings = []; + + // Check filename issues + if (incorrectFilesRaw) { + const filesList = incorrectFilesRaw.split(',').map(f => `- <code>${f}</code>`).join('\n'); + warnings.push( + '**Incorrect filename:**', + '', + filesList, + '', + `**Expected naming:** <code>${expectedPrefix}<descriptive-name>.md</code>`, + '', + `Rename your proposal file to use PR #${prNumber}:`, + '', + '```bash', + `git mv proposals/000-<name>.md ${expectedPrefix}<name>.md`, + '```' + ); + } + + // Check title issues + if (incorrectTitlesRaw) { + const titlesList = incorrectTitlesRaw.split(',').map(f => `- <code>${f}</code>`).join('\n'); + if (warnings.length > 0) warnings.push('', '---', ''); + warnings.push( + '**Incorrect title format:**', + '', + titlesList, + '', + `**Expected title format:** <code># ${prNumber} - <Your Title></code>`, + '', + `Update the H1 heading in your proposal to include the PR number:`, + '', + '```markdown', + `# ${prNumber} - My Feature Title`, + '```' + ); + } + + const warningSection = [ + '---', + '', + '## ⚠️ Proposal Numbering', + '', + 'This PR contains proposal files that don\'t follow the expected format:', + '', + ...warnings, + '', + 'See [proposals/README.md](https://github.com/kroxylicious/design/blob/main/proposals/README.md) for the complete workflow.', + '', + '<!-- proposal-numbering-check -->' + ].join('\n'); + + // Get current PR + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + + let currentBody = pr.body || ''; + + // Remove existing warning section if present + const markerRegex = /---\s*\n\s*##\s*⚠️\s*Proposal (File )?Numbering[\s\S]*?<!-- proposal-numbering-check -->/; + currentBody = currentBody.replace(markerRegex, '').trim(); + + // Append new warning section + const newBody = currentBody + '\n' + warningSection; + + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + body: newBody + }); + + - name: Remove warning from PR description if numbering is correct + if: steps.check.outputs.has_proposal == 'true' && steps.check.outputs.incorrect == 'false' + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 + with: + script: | + const prNumber = context.payload.pull_request.number; + + // Get current PR + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + + let currentBody = pr.body || ''; + + // Check if warning section exists + const markerRegex = /---\s*\n\s*##\s*⚠️\s*Proposal (File )?Numbering[\s\S]*?<!-- proposal-numbering-check -->/; + + if (markerRegex.test(currentBody)) { + // Remove warning section + const newBody = currentBody.replace(markerRegex, '').trim(); + + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + body: newBody + }); + + console.log('Removed numbering warning from PR description - file is now correctly named'); + } diff --git a/notify-open-prs.sh b/notify-open-prs.sh new file mode 100755 index 0000000..d6a1af5 --- /dev/null +++ b/notify-open-prs.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +# Copyright Kroxylicious Authors. +# +# Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 +# + +# Script to notify authors of open proposal PRs to rebase on main +# Once they rebase, the workflow will automatically check their proposal numbering + +set -e + +OPEN_PRS=(70 82 83 85 88 93 94 96 98 99 100 101 103) + +COMMENT_BODY="Hi! We've updated the proposal numbering system to use PR numbers as proposal identifiers. + +**Action required:** Please rebase your PR on \`main\`. + +Once you push, the GitHub workflow will automatically check your proposal file naming and update this PR description with specific instructions if your file needs to be renamed. + +See [proposals/README.md](https://github.com/kroxylicious/design/blob/main/proposals/README.md) for the updated workflow." + +echo "This script will comment on ${#OPEN_PRS[@]} open proposal PRs" +echo "" +read -p "Continue? (y/N) " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Aborted" + exit 1 +fi + +for pr in "${OPEN_PRS[@]}"; do + echo "Commenting on PR #$pr..." + gh pr comment "$pr" --body "$COMMENT_BODY" + echo "✓ PR #$pr notified" + sleep 2 # Be nice to the API +done + +echo "" +echo "✓ All open proposal PRs have been notified" +echo "" +echo "Once authors rebase, the workflow will automatically:" +echo " 1. Detect if their proposal file naming is incorrect" +echo " 2. Update their PR description with the exact command to fix it" +echo " 3. Remove the warning once they fix the naming" diff --git a/proposals/000-template.md b/proposals/000-template.md index 538db1e..7b4e99e 100644 --- a/proposals/000-template.md +++ b/proposals/000-template.md @@ -1,6 +1,19 @@ -<!-- This template is provided as an example with sections you may wish to comment on with respect to your proposal. Add or remove sections as required to best articulate the proposal. --> - -# <Title> +<!-- +PROPOSAL WORKFLOW: +1. Copy this template to: proposals/000-<descriptive-name>.md +2. Fill in your proposal content +3. Open a PR on GitHub +4. Rename the file to use your PR number: proposals/<PR#>-<descriptive-name>.md + Example: git mv proposals/000-my-feature.md proposals/105-my-feature.md +5. Update the heading below to include your PR number: # <PR#> - <Title> +6. Push the rename and updated title to your PR + +See proposals/README.md for complete instructions. + +This template is provided as an example with sections you may wish to comment on with respect to your proposal. Add or remove sections as required to best articulate the proposal. +--> + +# <PR-NUMBER> - <Title> Provide a brief summary of the feature you are proposing to add to Kroxylicious. diff --git a/proposals/README.md b/proposals/README.md new file mode 100644 index 0000000..1b596f4 --- /dev/null +++ b/proposals/README.md @@ -0,0 +1,39 @@ +# Kroxylicious Proposals + +This directory contains proposals for the Kroxylicious project. + +## Creating a New Proposal + +1. **Create your proposal file** using a placeholder name based on the [template](./000-template.md): + ``` + cp proposals/000-template.md proposals/000-<descriptive-name>.md + ``` + +2. **Commit and open a Pull Request**: + - Push your branch and open a PR on GitHub + - Note your PR number (e.g., #105) + +3. **Rename the file and update the title** to use your PR number (three-digit zero-padded): + ```bash + git mv proposals/000-<descriptive-name>.md proposals/105-<descriptive-name>.md + # Edit the file to update the title to: # 105 - <Your Title> + git commit -m "Rename proposal to use PR number" + git push + ``` + +4. **Announce** your proposal on the [mailing list](https://kroxylicious.io/join-us/mailing-lists/) + +5. **Discussion and approval**: The proposal will be discussed by the community + +6. **Merge**: Once approved, your proposal PR is merged to main. The proposal number remains the same as the PR number. + +## Finding Proposals + +- **Merged proposals:** Browse the directory listing above +- **Open proposals:** [View open proposal PRs](https://github.com/kroxylicious/design/pulls?q=is%3Apr+is%3Aopen) + +## Numbering + +Proposal numbers match PR numbers, using three-digit zero-padding (e.g., `092-`, `105-`). + +Proposals 001-019 predate this system and retain their original numbers.