elastic / elastic/integrations
[ci] Restore automatic team and integration labelling on issues and PRs
- Dominant language
- Handlebars
- Stars
- 333
- Forks
- 647
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 209
Description
# [ci] Restore automatic team and integration labelling on issues and PRs
## Problem
`Team:*` and `Integration:*` labels are applied entirely by hand today, and the
labelling conventions are documented only on a [wiki page](https://github.com/elastic/integrations/wiki/Label-Schema)
that is not enforced by any automation in this repository.
The gap is large and growing:
- **51% of open PRs** (98 of 193) carry no `Team:*` label. Example: PR #21084
touches `packages/iptables` and has no labels at all.
- **~38% of sampled open issues** (188 of 500) carry no `Team:*` label.
- **8 packages merged since 2026-07-31** have no `Integration:*` label:
`supabase`, `supabase_otel`, `vercel`, `temporal`, `anduril_lattice`,
`lite_llm`, `openai_chatgpt_enterprise`, `temporal_otel`.
The automation that previously applied these labels was external to the repository
and is no longer running (last observed activity: 2026-08-04).
## Impact beyond triage friction
- **`elastic/integration-experience`'s integration-review-bot** triggers its
automatic PR review off exactly three labels — `Team:Security-Service
Integrations`, `Team:Integration-Experience`, `Team:SDE-Crest`
(`integration-review-bot/integration_review_bot/poller/config.py`). A PR that
lands with no team label gets no automated review.
- **Several teams drive GitHub project boards off `Team:*` labels**, as noted in
the original proposal at elastic/integrations#10354.
- **CI-reported `flaky-test` issues** from `dev/testsreporter` already resolve
CODEOWNERS and mention owning teams as `@mentions` in the issue body
(`dev/testsreporter/_static/description.tmpl`), but `packageerror.go:115`
returns `nil` from `Labels()` — so those issues are never labelled either.
## Goal
Apply `Team:*` and `Integration:*` labels automatically when an issue or PR is
opened or updated, based on `.github/CODEOWNERS` and the package paths touched by
the diff. Ownership of this automation should sit inside the repository, not outside it.
## Proposed approach
A new GitHub Actions workflow triggered on `pull_request_target` (`opened`,
`synchronize`, `reopened`) and `issues` (`opened`):
1. **Resolve changed files → package paths → owning teams** by reading
`.github/CODEOWNERS`.
2. **Map teams → `Team:*` labels** using a maintained mapping (see Open
questions).
3. **Apply `Integration:` labels** where the corresponding label already
exists in the repository (do not create labels — that is out of scope).
4. **Never remove** labels already added by a human.
### Reuse existing CODEOWNERS tooling
**`dev/codeowners/codeowners.go`** provides `Owners.LoadOwners` /
`Owners.PackageOwnersByPath`, which already handles nested
`packages//` layouts and data-stream-level overrides. A small new
`cmd/` entrypoint wrapping it would give the workflow a single binary to invoke,
avoiding a third independent CODEOWNERS parser alongside the existing one at
`cmd/backport/codeowners/codeowners.go`. Consolidating the two parsers would be a
welcome clean-up if the implementer has appetite for it.
For issues, derive the package from the `Integration:*` label if one is present,
or from the package name in the issue template. Skip silently when no package can
be determined.
## Scope and constraints
- **Applies labels only.** Creating or renaming `Integration:*` label definitions
is explicitly out of scope and should be tracked separately.
- **Unmapped teams.** 12 of the 28 teams that appear in `CODEOWNERS` have no
corresponding `Team:*` label today:
`obs-signals-metrics-team`, `obs-ds-intake-services`, `obs-signals-logs-team`,
`obs-signals-traces-approvers`, `threat-research-and-detection-engineering`,
`kibana-management`, `actionable-obs-team`, `streams-ui`,
`security-generative-ai`, `logstash`, `ingest-managed-jobs`,
`customer-architects`, and the `apm-agent-*` teams. The workflow must no-op for
unmapped teams rather than fail or emit an error.
- **Label hygiene to resolve first.** Several label inconsistencies need
reconciling before a reliable mapping can be built:
`Team:Security-Service-Integrations` (null description) vs `Team:Security-Service
Integrations`; `Team:obs-infraobs-integrations` vs `Team:Obs-InfraObs`;
`Team: XDR` (null description, extra space).
- **Intentionally unowned paths.** `/.github/CODEOWNERS` has no owner by design
(validated by CI). `/packages/` maps to `@elastic/integrations-triaging`, which
should not produce a `Team:*` label.
- **`elastic/observability-dev` label sync.** `observability-dev/.github/labels/github-labels.yml`
syncs a subset of `Team:*` label definitions via
[github-label-sync](https://github.com/Financial-Times/github-label-sync). The
new workflow must not fight it — the two touch different things (definitions vs
assignment), so there should be no conflict, but it is worth verifying.
- **`pull_request_target` permissions.** The workflow needs `pull-requests: write`
and `issues: write`; everything else should stay at the minimum required.
## Open questions
- **Where does the GitHub-team → label mapping live?**
Two options:
1. A checked-in file next to `CODEOWNERS` (e.g. `.github/team-labels.yml`),
manually updated when teams change. Reviewable, versioned, and exactly what
elastic/integrations#10354 proposed.
2. Derived from the label descriptions themselves. Most `Team:*` descriptions
already embed the GitHub slug in brackets, e.g.
`Packages Ecosystem team [elastic/ecosystem]`. Zero upkeep, but brittle
where descriptions are null, missing the bracket format, or have typos (see
the hygiene list above).
A hybrid is also possible: start with (1) and add a CI check that keeps the
file in sync with the labels API.
- **Which team owns the workflow once it lands?** This should be decided at
implementation time so that `.github/CODEOWNERS` and the workflow itself have a
clear owner entry.
## Related
- elastic/integrations#10354 — prior proposal to label CI-failure issues at creation time
using a checked-in team→label mapping; still open
- [Label-Schema wiki page](https://github.com/elastic/integrations/wiki/Label-Schema) — the conventions this workflow would enforce
- `dev/codeowners/codeowners.go` — existing CODEOWNERS parser to reuse
- `cmd/backport/codeowners/codeowners.go` — second CODEOWNERS consumer; candidate
for consolidation
Contributor guide
Research direction
Start by reading dev/codeowners/codeowners.go and .github/CODEOWNERS to understand package ownership, then inspect existing workflows and observability-dev/.github/labels/github-labels.yml for label conventions. Define the mapping and workflow behavior from the stated constraints, and verify that opened or updated issues and pull requests receive applicable existing labels without removing human-added labels.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github-actions, go
- Domain
- ci-cd, devops, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100