Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 236 additions & 0 deletions .github/workflows/proposal-numbering.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
#
# 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 }}';

// Get all files that need fixing (union of incorrect filenames and incorrect titles)
const filesNeedingFix = new Set();
if (incorrectFilesRaw) {
incorrectFilesRaw.split(',').forEach(f => filesNeedingFix.add(f.trim()));
}
if (incorrectTitlesRaw) {
incorrectTitlesRaw.split(',').forEach(f => filesNeedingFix.add(f.trim()));
}

const warnings = [];

if (filesNeedingFix.size > 0) {
const files = Array.from(filesNeedingFix);
const filesList = files.map(f => `- <code>${f}</code>`).join('\n');

warnings.push(
'**Issues found:**',
'',
filesList,
''
);

// For each file, generate specific fix commands
files.forEach(file => {
const basename = file.replace('proposals/', '');
// Strip leading numbers or placeholder prefixes to get the descriptive part
const descriptive = basename.replace(/^[0-9]{3}-/, '').replace(/^(xxx|nnn|000)-/, '');
const expectedFilename = `proposals/${String(prNumber).padStart(3, '0')}-${descriptive}`;

const needsRename = file !== expectedFilename;
const needsTitleUpdate = incorrectTitlesRaw && incorrectTitlesRaw.includes(file);

if (needsRename || needsTitleUpdate) {
warnings.push(
`**Fix for <code>${file}</code>:**`,
'',
'```bash'
);

if (needsRename) {
warnings.push(`git mv ${file} ${expectedFilename}`);
}

if (needsTitleUpdate) {
const targetFile = needsRename ? expectedFilename : file;
warnings.push(
`# Update title: remove any old number prefix and add PR number`,
`sed -i.bak '0,/^# /{s/^# \\([0-9]\\{3\\}\\|xxx\\|nnn\\|000\\) - /# ${prNumber} - /; t; s/^# /# ${prNumber} - /}' ${targetFile} && rm ${targetFile}.bak`
);
}

warnings.push(
`git commit -m "Rename proposal to use PR number ${prNumber}"`,
'git push',
'```',
''
);
}
});

warnings.push(
'**Note:** The commands above can be copied and pasted directly into your terminal. The sed command will automatically preserve your title text.',
''
);
}

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');
}
45 changes: 45 additions & 0 deletions notify-open-prs.sh
Original file line number Diff line number Diff line change
@@ -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"
19 changes: 16 additions & 3 deletions proposals/000-template.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
42 changes: 42 additions & 0 deletions proposals/004-test-exact-commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!--
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.
-->

# 4 - Test Exact Commands

This is a test proposal to validate the workflow provides exact, copy-pasteable commands.

## Current situation

Describe the current capability Kroylicious has in this area.

## Motivation

Explain the motivation why this should be added, and what value it brings.

## Proposal

Provide an introduction to the proposal. Use sub sections to call out considerations, possible delivery mechanisms etc.

## Affected/not affected projects

Call out the projects in the Kroxylicious organisation that are/are not affected by this proposal.

## Compatibility

Call out any future or backwards compatibility considerations this proposal has accounted for.

## Rejected alternatives

Call out options that were considered while creating this proposal, but then later rejected, along with reasons why.
39 changes: 39 additions & 0 deletions proposals/README.md
Original file line number Diff line number Diff line change
@@ -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.
Loading