Skip to content

korg: add userinfo command for org and OWNERS lookup - #6398

Open
palnabarun wants to merge 1 commit into
kubernetes:mainfrom
palnabarun:korg/memberinfo
Open

palnabarun wants to merge 1 commit into
kubernetes:mainfrom
palnabarun:korg/memberinfo

Conversation

@palnabarun

@palnabarun palnabarun commented May 24, 2026

Copy link
Copy Markdown
Member

Adds korg userinfo <user>... to answer the recurring question this repo
exists for: which Kubernetes orgs is a user in, with what role, and where
do they appear in OWNERS files.

Sources:

  • GitHub user API for company / profile
  • config//org.yaml (Members / Admins) for k8s org membership
  • cs.k8s.io (hound) for OWNERS / OWNERS_ALIASES references

Behavior:

  • Honors GITHUB_TOKEN / GH_TOKEN to avoid the 60/hr unauth limit. GitHub
    and hound use separate http.Client instances, so the token is never
    sent to cs.k8s.io
  • Per-request context with a 30s timeout; SIGINT cancels in flight
  • Multi-user batches run concurrently (errgroup, bounded to 4) with
    output preserved in input order
  • One bad username does not kill the batch; per-user errors render in
    both text and JSON output, and the process exits non-zero
  • Hound failures degrade to a warning instead of dropping org info
  • --output json for scripting

OWNERS matching:

  • Anchors the hound query on "- " and keeps a hit only when the
    YAML list item equals the username exactly, so prose mentions,
    commented-out entries and substring near-misses ("- alice-bot" for
    "alice") are all dropped. Surrounding quotes and trailing inline
    comments are stripped first, so - "alice" and "- alice # area expert"
    still match
  • Each surviving hit is confirmed against the file's real content via
    gh api to exclude emeritus-only entries, toggled by --verify-owners.
    A hit that cannot be fetched is kept with a warning rather than dropped
  • Results render as an aligned REPO / PATH / URL table; the URL uses
    /blob/HEAD/ so the link resolves to the default branch

Tests:

  • Table-driven coverage of the OWNERS match filter (quoted values, inline
    comments, commented-out entries, substring near-misses), emeritus
    exclusion, and the fail-open path when a hit cannot be verified
  • Batch coverage for both output modes: input ordering, mixed
    success/failure runs, and the text renderer's company / orgs fallbacks
  • Asserts hound requests carry no Authorization header while GitHub
    requests stay authenticated

Dependencies:

  • adds github.com/google/go-github/v88 for the user API
  • promotes golang.org/x/sync from indirect v0.2.0 to direct v0.8.0 for
    errgroup
  • go directive 1.22.4 -> 1.25.0

(This PR has gotten assistance from AI tools)

@k8s-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: palnabarun

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added area/github-management Issues or PRs related to GitHub Management subproject cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. approved Indicates a PR has been approved by an approver from all required OWNERS files. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels May 24, 2026
@palnabarun

Copy link
Copy Markdown
Member Author

/assign @kubernetes/owners

@Priyankasaggu11929 Priyankasaggu11929 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @palnabarun!

left a few inline comments.

Comment thread cmd/korg/userinfo.go Outdated
Comment thread cmd/korg/userinfo.go Outdated
Comment thread cmd/korg/userinfo.go Outdated
Comment thread cmd/korg/userinfo.go
Comment thread cmd/korg/userinfo_test.go Outdated

@cblecker cblecker left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition — this fills a genuine gap and the overall structure is solid. The errgroup concurrency pattern is correct, Hound failures degrade gracefully, and it's good to see tests land alongside the new code. A few things worth addressing before this merges, mostly around the JSON output dropping failed users and a double-print in main(). The go.mod changes are covered separately.

Comment thread go.mod Outdated
Comment thread go.mod Outdated
Comment thread cmd/korg/korg.go Outdated
Comment thread cmd/korg/userinfo.go
Comment thread cmd/korg/userinfo.go
Comment thread cmd/korg/userinfo.go
Comment thread cmd/korg/userinfo.go Outdated
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: palnabarun

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow kubernetes-prow Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jul 3, 2026
@palnabarun

Copy link
Copy Markdown
Member Author

@Priyankasaggu11929 @cblecker PTAL again. Thank you. 🙏🏽

@palnabarun
palnabarun force-pushed the korg/memberinfo branch 2 times, most recently from c575655 to 65a1640 Compare July 3, 2026 11:19
Comment thread cmd/korg/userinfo_test.go

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The batch path is the most complex control flow here but only gets tested with single-user inputs. A mixed-batch test (e.g. ["alice", "ghost", "bob"] where ghost 404s) would exercise both branches of the JSON assembly loop in a single call and catch ordering / nil-dereference regressions.

Comment thread cmd/korg/userinfo_test.go

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Text mode is the default output but has no test coverage -- all runUserinfo tests pass outputJSON=true. A TestRunUserinfoText that checks for the === username header, Company: line, Orgs: section, and tabwriter table would guard against formatting regressions in renderText.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestRunUserinfoText covers the happy path now. A few edge branches in text mode are still untested: the ERROR block (lines 433-435), the Company: **Not Found** fallback for empty company, and the (none) display for empty orgs. A mixed-batch text test (similar to TestRunUserinfoJSONMixedBatch but with outputJSON=false) would close the gap.

@kubernetes-prow kubernetes-prow Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jul 6, 2026
@palnabarun

Copy link
Copy Markdown
Member Author

@cblecker addressed all four: nil-guard on the JSON error entry, tightened the "- " match to require an exact username (not just substring) after the dash, and added tests for the mixed-batch case and the default text-mode renderer. PTAL 🙏🏽

Comment thread cmd/korg/userinfo.go Outdated
return err
}

hc := &http.Client{Timeout: defaultHTTPTimeout}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hc client is shared between newGitHubClient and searchOwnerFiles. The go-github library mutates the provided http.Client's Transport in-place to inject Authorization: Bearer <token> headers. After newGitHubClient(hc) returns, every subsequent hc.Do(req) — including hound requests to cs.k8s.io — sends the GitHub token.

Fix: use separate http.Client instances for GitHub API and hound requests.

Comment thread cmd/korg/userinfo.go
default:
info.OwnerFiles = make([]OwnerFile, 0, len(hits))
for _, hit := range hits {
content, err := fetchOwnerFileContent(ctx, hit.Repo, hit.Path)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fail-open behavior here (keep the hit + add a warning when verification fails) is a deliberate design choice, but no test exercises it. If someone refactored this to drop unverifiable hits, no test would break.

Consider adding a subtest where stubGHCLI returns an error for one of two hits, then assert both hits are preserved and a warning is emitted.

Adds `korg userinfo <user>...` to answer the recurring question this repo
exists for: which Kubernetes orgs is a user in, with what role, and where
do they appear in OWNERS files.

Sources:
- GitHub user API for company / profile
- config/<org>/org.yaml (Members / Admins) for k8s org membership
- cs.k8s.io (hound) for OWNERS / OWNERS_ALIASES references

Behavior:
- Honors GITHUB_TOKEN / GH_TOKEN to avoid the 60/hr unauth limit. GitHub
  and hound use separate http.Client instances, so the token is never
  sent to cs.k8s.io
- Per-request context with a 30s timeout; SIGINT cancels in flight
- Multi-user batches run concurrently (errgroup, bounded to 4) with
  output preserved in input order
- One bad username does not kill the batch; per-user errors render in
  both text and JSON output, and the process exits non-zero
- Hound failures degrade to a warning instead of dropping org info
- `--output json` for scripting

OWNERS matching:
- Anchors the hound query on "- <user>" and keeps a hit only when the
  YAML list item equals the username exactly, so prose mentions,
  commented-out entries and substring near-misses ("- alice-bot" for
  "alice") are all dropped. Surrounding quotes and trailing inline
  comments are stripped first, so `- "alice"` and "- alice # area expert"
  still match
- Each surviving hit is confirmed against the file's real content via
  `gh api` to exclude emeritus-only entries, toggled by --verify-owners.
  A hit that cannot be fetched is kept with a warning rather than dropped
- Results render as an aligned REPO / PATH / URL table; the URL uses
  /blob/HEAD/ so the link resolves to the default branch

Tests:
- Table-driven coverage of the OWNERS match filter (quoted values, inline
  comments, commented-out entries, substring near-misses), emeritus
  exclusion, and the fail-open path when a hit cannot be verified
- Batch coverage for both output modes: input ordering, mixed
  success/failure runs, and the text renderer's company / orgs fallbacks
- Asserts hound requests carry no Authorization header while GitHub
  requests stay authenticated

Dependencies:
- adds github.com/google/go-github/v88 for the user API
- promotes golang.org/x/sync from indirect v0.2.0 to direct v0.8.0 for
  errgroup
- go directive 1.22.4 -> 1.25.0

Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
@palnabarun

Copy link
Copy Markdown
Member Author

/test pull-org-verify-all

Comment thread cmd/korg/userinfo_test.go
return nil, fmt.Errorf("unexpected gh invocation: %v", args)
})

ghHits := 0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: ghHits is incremented but never read or asserted on — it's dead code. Either remove it or add an assertion like if ghHits == 0 { t.Error("expected at least one GitHub API call") } to make the intent explicit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. area/github-management Issues or PRs related to GitHub Management subproject cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants