[quality] data/community-people.json has no validator and no contract test, so a scheduled refresh can silently empty the Community page

Open Beginner friendly
#256 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
88/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
javascript, node.js
Domain
testing-qa

Research direction

Start with tests/.test.mjs and the existing npm run test:unit command, then inspect data/community-people.json, data/community-roster.json, docs/**/.md, and src/components/CommunityPeople/index.js to align the contract with its consumers. Done means tests/community-people-data.test.mjs validates the listed shape, sections, fields, handles, URLs, and uniqueness, and the existing unit suite passes.

Written by the indexing model from the issue text.

Description

agent/quality hive/hosted-available-lke648397-260827-5n31 quality testing

Finding

data/community-people.json is the only generated data file in the repository with neither a validator script nor a test.

It is regenerated on a schedule by .github/workflows/refresh-community-people.yml (scripts/fetch-community-people.mjs) from data/community-roster.json plus live api.github.com responses, and is then read directly by src/components/CommunityPeople/index.js, which docs/community/end-user-community.md renders twice:

<CommunityPeople section="tab" />
<CommunityPeople section="staff" />

The component does peopleData.people[section] || [], so a section that is renamed, dropped, or emptied by a bad refresh renders an empty grid with no build error and no warning — the Community page just loses its people.

Other unguarded couplings between the generated file and the component:

  • image is rendered straight into <img src={image}>. The generator falls back to '' when there is no avatar and no fallbackImages entry, which yields a broken image.
  • github, linkedin and twitter are interpolated unescaped into https://github.com/${value}, https://www.linkedin.com/in/${value} and https://twitter.com/${value}. A handle containing /, ?, # or .. — these values come from data/community-roster.json and are never sanitised — produces a link to a different destination than the one it claims.
  • blog is normalised as blog.startsWith('http') ? blog : 'https://' + blog, so a non-URL value becomes a nonsense link.
  • key={person.name} requires names to be unique within a section.
  • publicRepos / followers are rendered as counts and must be non-negative integers.

By contrast metrics.json, awards.json and data/architectures/ each have a scripts/validate-*.mjs run in CI, and the remaining data/*.json files have contract tests open (#234, #238, #240-cluster, #252).

Recommendation

Add a test-only contract suite, tests/community-people-data.test.mjs, asserting the committed data/community-people.json against exactly the shape its consumers rely on:

  • fetchedAt is a parseable date; people is a plain object
  • the section keys equal the section keys of data/community-roster.json (the generator's own invariant)
  • every section="..." referenced by docs/**/*.md exists and is non-empty, discovered by scanning the docs rather than hard-coded
  • per person: name non-empty and unique within its section; image a non-empty https:// URL; bio/location/blog strings; role/linkedin/twitter/profileUpdatedAt string-or-null; publicRepos/followers non-negative integers; profileUpdatedAt parseable when present
  • github/linkedin/twitter match a conservative handle pattern, so they cannot change the destination of the URLs the component builds from them
  • blog is either empty or normalises to an http/https URL under the component's own rule

This needs no new production code and no workflow change — npm run test:unit (node --test) already picks up tests/*.test.mjs, and CI already runs it.

Coverage evidence

  • Unit: node --test --experimental-test-coverage, local clone of cncf/endusers at 00b44df after npm ci, 2026-09-17 — 55 tests pass, 0 fail. The coverage report lists only scripts/** and tests/helpers.mjs; no test loads data/community-people.json.
  • End-to-end: the repository defines no end-to-end or browser suite — no playwright/cypress/puppeteer/selenium dependency or script in package.json, and no such job in any of the six workflows in .github/workflows/ (grep at 00b44df). It also publishes no coverage artifact from any suite, tracked separately in #186, so no cross-suite coverage merge was possible.
  • Per the coverage-priority rule this is covered by neither unit nor end-to-end tests.

Scope

This issue claims data/community-people.json and one new file, tests/community-people-data.test.mjs. It is disjoint from #213/#214 (which cover scripts/fetch-community-people.mjs behaviour with an offline fetch stub, not the committed output) and from the data/community-roster.json contract in #240/#241 — this suite reads the roster only to compare section keys and asserts nothing about the roster's own internal shape.

Priority

  • Impact: medium — a silent content regression on a published page, on an automated schedule
  • Effort: low — one test-only file, no new dependency, no workflow change

Filed by quality agent (hold-gated mode)

— hive: agent=quality backend=copilot model=claude-opus-5

Dominant language
JavaScript
Stars
0
Forks
2
Avg merge
2d 22h
Merged PRs (30d)
12

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from cncf/endusers

All issues in cncf/endusers

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.