Skip to content

Commit 02ef85e

Browse files
authored
Merge pull request #5267 from BenTheElder/diff-kep-template
MVP: automatically diff KEP headings versus the template
2 parents 6c67c31 + e938036 commit 02ef85e

File tree

6 files changed

+157
-45
lines changed

6 files changed

+157
-45
lines changed

hack/diff-toc-vs-template.sh

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright 2025 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -o errexit
18+
set -o nounset
19+
set -o pipefail
20+
21+
# cd to the root path
22+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
23+
cd "${ROOT}"
24+
25+
MDTOC=(go tool -modfile="${ROOT}/hack/tools/mdtoc/go.mod" mdtoc)
26+
27+
# Identify KEP files changed by the PR:
28+
# default from prow env if unset from args
29+
# https://docs.prow.k8s.io/docs/jobs/#job-environment-variables
30+
# TODO: handle batch PR testing
31+
target=HEAD
32+
base="${BASE_COMMIT:-}"
33+
if [[ -z "${target:-}" && -n "${PULL_PULL_SHA:-}" ]]; then
34+
target="${PULL_PULL_SHA}"
35+
fi
36+
# target must be a something that git can resolve to a commit.
37+
# "git rev-parse --verify" checks that and prints a detailed
38+
# error.
39+
if [[ -n "${target}" ]]; then
40+
target="$(git rev-parse --verify "${target}")"
41+
fi
42+
if [[ -z "${base}" && -n "${PULL_BASE_SHA:-}" && -n "${PULL_PULL_SHA:-}" ]]; then
43+
if ! base="$(git merge-base "${PULL_BASE_SHA}" "${PULL_PULL_SHA}")"; then
44+
echo >&2 "Failed to detect base revision correctly with prow environment variables."
45+
exit 1
46+
fi
47+
elif [[ -z "${base}" ]]; then
48+
# origin is the default remote, but we encourage our contributors
49+
# to have both origin (their fork) and upstream, if upstream is present
50+
# then prefer upstream
51+
# if they have called it something else, there's no good way to be sure ...
52+
remote='origin'
53+
if git remote | grep -q 'upstream'; then
54+
remote='upstream'
55+
fi
56+
default_branch="$(git rev-parse --abbrev-ref "${remote}"/HEAD | cut -d/ -f2)"
57+
if ! base="$(git merge-base "${remote}/${default_branch}" "${target:-HEAD}")"; then
58+
echo >&2 "Could not determine default base revision. -r must be used explicitly."
59+
exit 1
60+
fi
61+
fi
62+
base="$(git rev-parse --verify "${base}")"
63+
64+
echo "base: $base target: $target"
65+
66+
readonly template_readme='keps/NNNN-kep-template/README.md'
67+
68+
# get TOC for template
69+
readonly mdtoc_options=(
70+
# make sure to include all headings for this purpose even if we
71+
# wouldn't surface them in the checked-in toc in update-toc.sh
72+
'--max-depth' '100'
73+
)
74+
template_toc=$("${MDTOC[@]}" "${mdtoc_options[@]}" "${template_readme}")
75+
76+
result=0
77+
# get KEP README files changed in the diff
78+
kep_readmes=()
79+
while IFS= read -r changed_file
80+
do
81+
# make sure to ignore the template kep itself, we don't want to self-diff
82+
if [[ "${changed_file}" == "keps"*"README.md" ]] && [[ "${changed_file}" != "${template_readme}" ]]; then
83+
kep_readmes+=("${changed_file}")
84+
fi
85+
done < <(git diff-tree --no-commit-id --name-only -r "${base}".."${target}")
86+
87+
for kep_readme in "${kep_readmes[@]}"; do
88+
kep_toc=$("${MDTOC[@]}" "${mdtoc_options[@]}" "${kep_readme}")
89+
echo >&2 "Diffing table of contents for $kep_readme:"
90+
# diff only removals versus the template
91+
# we don't care about _additional_ headings in the KEP
92+
# we also don't care if (Optional) headings are missing
93+
git diff <(echo "${template_toc}" ) <(echo "${kep_toc}" ) \
94+
| grep -E '^-' \
95+
| grep -v '(Optional)' \
96+
|| result=-1
97+
done
98+
99+
100+
echo >&2 "Checked: ${kep_readmes[@]}"
101+
echo >&2 "Result: ${result}"
102+
exit "${result}"
103+

hack/tools/mdtoc/go.mod

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module k8s.io/enhancements/hack/tools/mdtoc
2+
3+
go 1.25
4+
5+
tool sigs.k8s.io/mdtoc
6+
7+
require (
8+
github.com/BurntSushi/toml v0.3.1 // indirect
9+
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
10+
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect
11+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
12+
github.com/mmarkdown/mmark v2.0.40+incompatible // indirect
13+
github.com/spf13/cobra v1.8.1 // indirect
14+
github.com/spf13/pflag v1.0.5 // indirect
15+
sigs.k8s.io/mdtoc v1.4.0 // indirect
16+
sigs.k8s.io/release-utils v0.8.3 // indirect
17+
)

hack/tools/mdtoc/go.sum

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
2+
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
3+
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ=
4+
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=
5+
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
6+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
7+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8+
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU=
9+
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
10+
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
11+
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
12+
github.com/mmarkdown/mmark v2.0.40+incompatible h1:vMeUeDzBK3H+/mU0oMVfMuhSXJlIA+DE/DMPQNAj5C4=
13+
github.com/mmarkdown/mmark v2.0.40+incompatible/go.mod h1:Uvmoz7tvsWpr7bMVxIpqZPyN3FbOtzDmnsJDFp7ltJs=
14+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
15+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
16+
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
17+
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
18+
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
19+
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
20+
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
21+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
22+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
23+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
24+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
25+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
26+
sigs.k8s.io/mdtoc v1.4.0 h1:2pDEwJSjoVrGr5BPkG+LoLkYLKvgtGYurrBY8ul3SxQ=
27+
sigs.k8s.io/mdtoc v1.4.0/go.mod h1:KVnRRtK1rX9aQ95qF0rt3x2ytTxf3r7W7N41H+0KF0k=
28+
sigs.k8s.io/release-utils v0.8.3 h1:KtOtA4qDmzJyeQ2zkDsFVI25+NViwms/o5eL2NftFdA=
29+
sigs.k8s.io/release-utils v0.8.3/go.mod h1:fp82Fma06OXBhEJ+GUJKqvcplDBomruK1R/1fWJnsrQ=

hack/update-toc.sh

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,16 @@ set -o errexit
1818
set -o nounset
1919
set -o pipefail
2020

21-
# keep in sync with hack/verify-toc.sh
22-
TOOL_VERSION=v1.1.0
23-
2421
# cd to the root path
2522
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
2623
cd "${ROOT}"
2724

28-
# create a temporary directory
29-
TMP_DIR=$(mktemp -d)
30-
31-
# cleanup
32-
exitHandler() (
33-
echo "Cleaning up..."
34-
rm -rf "${TMP_DIR}"
35-
)
36-
trap exitHandler EXIT
37-
38-
# Perform go install in a temp dir as we are not tracking this version in a go
39-
# module.
40-
# If we do the go install in the repo, it will create/update go.mod and go.sum.
41-
cd "${TMP_DIR}"
42-
GO111MODULE=on GOBIN="${TMP_DIR}" go install "sigs.k8s.io/mdtoc@${TOOL_VERSION}"
43-
export PATH="${TMP_DIR}:${PATH}"
44-
cd "${ROOT}"
25+
MDTOC=(go tool -modfile="${ROOT}/hack/tools/mdtoc/go.mod" mdtoc)
4526

4627
# Update tables of contents if necessary.
4728
find keps -name '*.md' \
4829
| grep -Fxvf hack/.notableofcontents \
49-
| xargs mdtoc --inplace --max-depth=5 || (
30+
| xargs "${MDTOC[@]}" --inplace --max-depth=5 || (
5031
echo "Failed generating TOC. If this failed silently and you are on mac, try 'brew install grep'"
5132
exit 1
5233
)

hack/verify-toc.sh

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,17 @@ set -o errexit
1818
set -o nounset
1919
set -o pipefail
2020

21-
# keep in sync with hack/update-toc.sh
22-
TOOL_VERSION=v1.1.0
23-
2421
# cd to the root path
2522
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
2623
cd "${ROOT}"
2724

28-
# create a temporary directory
29-
TMP_DIR=$(mktemp -d)
30-
31-
# cleanup
32-
exitHandler() (
33-
echo "Cleaning up..."
34-
rm -rf "${TMP_DIR}"
35-
)
36-
trap exitHandler EXIT
37-
38-
# perform go install in a temp dir as we are not tracking this version in a go module
39-
# if we do the go install in the repo, it will create / update a go.mod and go.sum
40-
cd "${TMP_DIR}"
41-
GO111MODULE=on GOBIN="${TMP_DIR}" go install "sigs.k8s.io/mdtoc@${TOOL_VERSION}"
42-
export PATH="${TMP_DIR}:${PATH}"
43-
cd "${ROOT}"
25+
MDTOC=(go tool -modfile="${ROOT}/hack/tools/mdtoc/go.mod" mdtoc)
4426

4527
echo "Checking table of contents are up to date..."
4628
# Verify tables of contents are up-to-date
4729
find keps -name '*.md' \
4830
| grep -Fxvf hack/.notableofcontents \
49-
| xargs mdtoc --inplace --max-depth=5 --dryrun || (
31+
| xargs "${MDTOC[@]}" --inplace --max-depth=5 --dryrun || (
5032
echo "Table of content not up to date. Did you run 'make update-toc' ?"
5133
echo "If this failed silently and you are on mac, try 'brew install grep'"
5234
exit 1

keps/NNNN-kep-template/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ tags, and then generate with `hack/update-toc.sh`.
9191
- [Non-Goals](#non-goals)
9292
- [Proposal](#proposal)
9393
- [User Stories (Optional)](#user-stories-optional)
94-
- [Story 1](#story-1)
95-
- [Story 2](#story-2)
94+
- [Story 1 (Optional)](#story-1-optional)
95+
- [Story 2 (Optional)](#story-2-optional)
9696
- [Notes/Constraints/Caveats (Optional)](#notesconstraintscaveats-optional)
9797
- [Risks and Mitigations](#risks-and-mitigations)
9898
- [Design Details](#design-details)
@@ -218,9 +218,9 @@ the system. The goal here is to make this feel real for users without getting
218218
bogged down.
219219
-->
220220

221-
#### Story 1
221+
#### Story 1 (Optional)
222222

223-
#### Story 2
223+
#### Story 2 (Optional)
224224

225225
### Notes/Constraints/Caveats (Optional)
226226

0 commit comments

Comments
 (0)