Kubernetes 指导委员会选举提名模板(nomination-template.md)结构与自动化校验实战
【免费下载链接】communityKubernetes Community Documentation项目地址: https://gitcode.com/GitHub_Trending/com/community
本篇以 Kubernetes 社区仓库(community)中 2023 年 Steering Committee 选举使用的提名模板 nomination-template.md 为主体,完整拆解模板的 YAML 头部、命名规则与四个固定章节,并结合仓库内置的自动化校验工具 verify-steering-election-tool.go 的源码,说明一份候选人简介(bio)文件在合并前会被机器检查哪些规则、常见格式错误如何触发校验失败,以及 2023 年真实候选人文件长什么样。读完本文,你可以独立写出一份能直接通过 CI 校验、符合选举流程要求的提名文件。
一、这个模板是什么:Steering 选举中的角色定位
Kubernetes 指导委员会(Steering Committee)选举按年度在elections/steering/目录下按年份归档,elections/steering/README.md 说明该目录“包含 2017 年以来的所有 Kubernetes Steering 选举资料”,并以当年目录作为选举的唯一事实来源(single source of truth)。
模板文件本身只承担一件事:为候选人简介提供统一格式,让所有候选人的信息可以被一致地展示(渲染到 Elekto 选举应用中)和被机器自动校验。它由三部分构成:
- 以 61 个短横线围成的 YAML 头部:候选人元数据(姓名、GitHub ID、雇主、Slack);
- 四个固定的 H2 章节:SIGs、What I have done、What I'll do、Resources About Me;
- 一条 HTML 注释:提醒使用者“把本模板复制为
candidate-githubid.md并保存到选举目录”。
模板原文全文如下(来自 nomination-template.md)):
------------------------------------------------------------- name: ID: GitHubID info: - employer: Your Employer or "Independent" - slack: slack handle ------------------------------------------------------------- <!-- Please make a copy of this template as "candidate-githubid.md" and save it to the election directory --> ## SIGS - SIGS/WG/UGs you're a member of ## What I have done ## What I'll do ## Resources About Me - Links to KubeCon or other conference talks or other related material - Links to social media2023 年的选举背景与流程细节(提名、背书、投票、时间表、选举官名单)完整记录在同目录的 README.md 中,模板的使用必须放在这套流程里理解——下一节先把流程走一遍,再回到模板字段逐条讲。
二、提名流程:模板文件在整个选举中的位置
根据 2023 选举 README 的Candidacy Process,一名候选人从提名到公示简介要经过五步,模板出现在最后一步:
- 创建提名 issue:在 community 仓库创建 issue,标题格式为
Steering Committee Nomination: Your Name (@yourgithub);他人提名需事先征得本人同意。 - 邮件通知:向 dev@kubernetes.io 发送邮件,主题与 issue 标题一致,正文附上 issue 链接并邀请有投票资格的人到 issue 下 +1(邮件里的 +1 不计入资格)。
- 接受提名:被提名人在提名issue(不是邮件)下回复类似 "I accept the nomination"。
- 用 PR 关闭 issue:候选人提交添加简介的 Pull Request,PR 正文必须包含
Fixes #NNN(NNN 为提名 issue 编号),合并后自动关闭 issue。 - 按模板编写简介文件:复制该目录下的
nomination-template.md,新建一个名为candidate-githubid.md的文件,填完所有字段,且不要做任何格式改动(avoid making any format changes)。
其余关键规则:
- 字数:全部正文(biographical statements)建议总计约300 词,过长会被要求删减后才能合并。
- 背书:需获得 3 名来自 3 个不同雇主的合格选民的背书(endorsement),本人若具备投票资格可算一人;只有 GitHub issue 下的背书有效,提名邮件下的无效。
- 截止时间:提名(8 月 26 日)与简介(8 月 27 日)的截止均按AoE(Anywhere on Earth,UTC-12)当日结束计,2023 年时间表完整列于 README.md 的 Schedule 小节。
- 逾期处理:候选人错过截止时间的情况由选举委员会逐案裁定资格。
目录的 OWNERS 文件把 approvers 配置为选举委员会committee-steering与三位选举官(kaslin、bridgetkromhout、dims),意味着简介 PR 正是由这组人在代码评审层面把关格式。
三、模板逐段拆解:字段、格式与取值
3.1 YAML 头部:61 个短横线的“定界符”
头部由上下两条分隔线围住,每条分隔线是恰好 61 个-字符:
------------------------------------------------------------- name: ID: GitHubID info: - employer: Your Employer or "Independent" - slack: slack handle -------------------------------------------------------------各字段含义与填写要求:
| 字段 | 说明 | 填写示例 |
|---|---|---|
name | 候选人真实姓名 | Arnaud Meukam |
ID | 候选人的 GitHub ID,必须与文件名中的用户名完全一致 | ameukam |
info | 结构化联系信息,YAML 列表形式,每项为单键映射 | 见下 |
info[].employer | 雇主名称;独立贡献者填"Independent" | VMware |
info[].slack | 候选人在社区 Slack 中的 handle | Arnaud |
info采用- employer: xxx这种“列表内含单键映射”的写法,是 Elekto 应用的既有约定。校验源码 verify-steering-election-tool.go 中有一条 TODO 注释说明了来龙去脉:
// TODO: Have Elekto accept both mapping and sequence forms for candidate info // so compatibility is enforced at the application boundary as well as here.
对应地,InfoData的自定义UnmarshalYAML同时接受mapping和sequence两种写法(L57-L82),把 sequence 形式拍平为map[string]string——因此映射形式info:\n employer: X也能通过仓库侧校验,但模板默认、且与 2023 年所有真实候选人文件一致的形式是 sequence 形式。
为什么是 61 个短横线?校验工具用一个正则来提取头部(L36):
var yamlHeaderRegex = regexp.MustCompile(`(?s)^-{61}\s*\n(.*?)\n-{61}\s*\n`)分隔线必须是文件开头的恰好 61 个-(行尾可带空格,L347-L355 的extractYAMLHeader注释明确写道 “The format requires exactly 61 dashes for consistency”)。测试用例 verify-steering-election-tool_test.go 专门验证了 60 个短横线的输入会失败(wantErr: true)。结论:复制模板时分隔线一个字符都不能增删改。
3.2 文件名规则:candidate-githubid.md
- 文件名必须匹配正则
^candidate-([a-zA-Z0-9_-]+)\.md$(L245-L248),即candidate-前缀 + GitHub 用户名 +.md后缀,仅允许字母、数字、下划线、短横线。 - 文件名中的用户名必须与头部
ID字段逐字符相等(L271-L284),不一致时报告filename username '...' does not match GitHub ID '...' in header。 - 因此命名是机械操作:GitHub ID 为
justaugustus的人,文件就是candidate-justaugustus.md——2023 年目录下 11 个候选人文件(如 candidate-justaugustus.md、candidate-ameukam.md)全部符合这一规则。
3.3 四个固定章节及其写法要求
正文必须包含以下四个 H2 章节(顺序与模板一致,不要改动标题):
## SIGS:列出所参与的 SIG/WG/UG 及其中角色。校验工具对标题大小写宽容——## SIGS或## SIGs均视为通过(L323-L342),但其余三个章节标题必须精确匹配。## What I have done:过往贡献(角色、推动的项目、基础设施/发布经历等)。## What I'll do:当选后的计划。选举章程要求候选人以“brand free”(去公司标签)的个人身份参选,基于对社区的贡献而非公司职位来陈述,README 的Campaigning小节对此有明确约束。## Resources About Me:KubeCon 或其他会议的演讲链接、相关作品与社交媒体链接。
章节内内容可选(Biography statements are optional),但章节标题本身是必填项:缺任何一节都会被工具以missing required section: ...报错。
3.4 字数上限:450 是硬限,300 是建议线
工具定义了两个常量(L30-L34):
const ( maxWordCount = 450 recommendedWordCount = 300 startYear = 2026 )- 正文超过450 词直接判定为无效文件;失败输出会提示 “Bios should be limited to around 300 words, excluding headers.”
- 统计方式值得注意:计数前先用
yamlHeaderRegex把整个 YAML 头部剔除(L217-L236),再按空白符切分计数。也就是说头部元数据不占字数,但正文里的 Markdown 标记(如列表符-、链接里的文字)都会计入单词。测试用例 TestCountWords 覆盖了换行、多空格、纯空白、含头部剔除等边界场景。
四、对照实例:2023 年真实候选人文件如何填模板
以 candidate-ameukam.md 为例,可以看到模板填写后的完整形态:
------------------------------------------------------------- name: Arnaud Meukam ID: ameukam info: - employer: VMware - slack: Arnaud ------------------------------------------------------------- ## SIGS - SIG K8s Infra: SIG Chair - SIG Release: Release Manager Associate - SIG Testing ## What I have done I have been involved with the Kubernetes project since 2018. ... - Boostrap registry.k8s.io as the new distribution platform for our container images ... ## What I'll do As a member of the community, I am committed to pushing the project's progress ... ## Resources About Me - Twitter: [@ameukam](https://twitter.com/ameukam) - Talks: - Why We Moved the Kubernetes Image Registry ...对照模板可以核对三个要点:
- 头部字段全部填实:
name写全名、ID与文件名candidate-ameukam.md中的ameukam一致、info保留 sequence 形式并填了employer与slack; - 四个章节标题原样保留,
## SIGS中用列表写明所参与的 SIG 与担任的角色; - 正文是“贡献事实 + 施政主张 + 外部链接”的结构,未新增任何模板之外的章节。
其余 2023 年候选人文件(candidate-pacoxu.md、candidate-pohly.md、candidate-vincepri.md 等)均可作为风格与篇幅参照。
五、自动化校验:verify-steering-election-tool 的完整检查链
模板格式不只是靠人工评审保证的。仓库提供了命令行工具,verify-steering-election.sh 是入口脚本:
# hack/verify-steering-election.sh cd "$(dirname "${BASH_SOURCE[0]}")/.." go run hack/verify-steering-election-tool.go elections它从仓库根目录运行 Go 工具并扫描elections目录。工具的主流程(main)对每个检出的 bio 文件依次执行四类检查:
- 字数检查
countWords:剔除 YAML 头部后统计单词数,超过 450 即报错has N words。 - 文件名与 GitHub ID 一致性
validateFileNameAndGitHubID:文件名必须符合candidate-username.md,且与头部ID相等(L238-L287)。 - 模板合规性
validateTemplateCompliance(L289-L345):- 头部必须可解析且
name、ID非空; info中必须包含选举配置要求公示的全部字段——工具从同目录的election.yaml读取show_candidate_fields(L156-L169),逐个检查info.<field>非空,缺失时报missing required field: info.slack这类错误;- 四个必需章节标题必须存在。
- 头部必须可解析且
- 年份过滤
findBioFiles:只校验路径含/2026/至“当前年份+5”范围内目录中的candidate-*.md文件(L171-L215)。
任何一项失败,工具会逐条打印文件: 原因,最后输出N invalid Steering Committee election bio(s) detected.并以退出码 1 结束,阻断 PR 合并。对应的单元测试 verify-steering-election-tool_test.go 对每个函数都写了正反用例,包括:61 vs 60 个短横线、mapping vs sequence 形式的info、文件名不匹配、缺name/ID/info.slack、缺 SIGs 章节、## SIGs大小写变体、以及年份窗口(2025 年的文件不校验、2026 年起校验、超出 5 年的未来年份不校验)。
常见校验失败与原因速查
| 错误信息(节选) | 触发原因 | 修复方式 |
|---|---|---|
filename must follow format 'candidate-username.md' | 文件名不是candidate-前缀加合法用户名,或扩展名不是.md | 按 GitHub ID 重命名文件 |
filename username 'x' does not match GitHub ID 'y' in header | 文件名与头部ID不一致 | 使二者逐字符相同 |
could not find YAML header between dashes | 分隔线不是恰好 61 个-,或未位于文件开头 | 原样复制模板分隔线,勿改动 |
info must be a mapping or sequence | info写成了标量(如info: xxx) | 恢复列表/映射形式 |
missing required field: name / ID / info.employer / info.slack | 头部字段缺失或为空 | 按模板逐字段填实 |
missing required section: What I'll do等 | 缺少固定章节标题 | 保留模板中的四个 H2 标题 |
has 480 words | 正文超过 450 词 | 压缩到约 300 词(头部不计入) |
六、与选举配置的联动:election.yaml 如何驱动校验
2023 年选举的配置 election.yaml 同时服务于 Elekto 应用和上述校验工具,关键字段:
name: 2023 Steering Committee Election organization: Kubernetes start_datetime: 2023-08-29 00:00:01 end_datetime: 2023-09-27 11:59:59 no_winners: 4 allow_no_opinion: True delete_after: True show_candidate_fields: - employer - slack election_officers: - dims - kaslin - bridgetkromhout eligibility: Kubernetes Org members with 50 or more contributions in the last year can vote. ... exception_description: Not all contributions are measured by DevStats. ... exception_due: 2023-09-24 11:59:59要点:
no_winners: 4对应 2023 年选出 4 名任期两年的委员;election_desc.md 说明了该季度另有 3 名现任成员(@BenTheElder、@mrbobbytables、@palnabarun)继续履职。show_candidate_fields声明employer与slack两字段,这正是校验工具强制候选人info中必须非空的两项(见 TestValidateTemplateCompliance 中candidateFields := []string{"employer", "slack"}),也是选举应用向公众展示候选人身份的来源。election_officers(dims、kaslin、bridgetkromhout)与 OWNERS 的 approvers 及 README 中列出的选举官名单(Kaslin Fields、Davanum Srinivas、Bridget Kromhout)互相印证,三位选举官同时是简介 PR 的审批人。- 投票规则方面,2023 年采用限时 Condorcet 排序投票(允许 "no opinion",与
allow_no_opinion: True对应),平票由无利益关联的 SC 成员掷硬币决定,均见 README.md 的 Voting Process 小节。
需要说明的适用前提:校验工具当前只对 2026 年及以后的选举目录强制执行(startYear = 2026),2023 年目录中的文件是通过人工评审保障格式的;但 2023 年全部候选人文件事实上都满足工具所检查的每一条规则,可作为格式基准。
七、可复用的操作清单
结合模板原文、2023 年 README 流程与校验工具规则,写一份合规提名简介的操作清单如下:
- 复制 nomination-template.md 为
candidate-<你的GitHubID>.md,放入当年选举目录; - 保持两条 61 短横线的分隔线原样不动,填实
name(全名)、ID(GitHub ID,与文件名一致)、info的employer(公司或"Independent")与slack(Slack handle),保留- key: value的列表形式; - 依次填写四个章节,标题保持
## SIGS、## What I have done、## What I'll do、## Resources About Me不变; - 控制正文总字数在 300 词左右(硬上限 450 词,头部不计入);
- 在提名 issue 上确认已获得 3 名来自 3 个不同雇主的合格选民背书;
- 提交 PR,正文写
Fixes #<提名issue编号>,由选举官/委员会(见目录 OWNERS)评审合并; - 提交前可自行对照第五节的“常见校验失败速查”表逐项自查,或本地执行 hack/verify-steering-election.sh 中
go run hack/verify-steering-election-tool.go elections的同款逻辑核对格式。
掌握以上内容后,提名模板不再是“照抄填空”的动作,而是一套可预测、可自查、可通过自动化校验的格式契约:文件名 ↔ID字段 ↔ 61 短横线头部 ↔show_candidate_fields字段 ↔ 四个固定章节 ↔ 450 词上限,任何一环不满足都会被 verify-steering-election-tool.go 明确点名。
【免费下载链接】communityKubernetes Community Documentation项目地址: https://gitcode.com/GitHub_Trending/com/community
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考