Skip to content

feat(tag): comma-separated --level (e.g. --level pipeline,job)#2388

Merged
Drarig29 merged 4 commits into
DataDog:masterfrom
eliebleton-manomano:feat/multi-level-tag
Jul 2, 2026
Merged

feat(tag): comma-separated --level (e.g. --level pipeline,job)#2388
Drarig29 merged 4 commits into
DataDog:masterfrom
eliebleton-manomano:feat/multi-level-tag

Conversation

@eliebleton-manomano

@eliebleton-manomano eliebleton-manomano commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What and why

Makes --level on datadog-ci tag additive: it now accepts a comma-separated list, so the same tags can be applied to several spans in one invocation (e.g. --level pipeline,job).

Tags don't propagate between spans, and the level they belong on isn't always singular — e.g. team is useful at every level, and job_maintainer belongs on both job and step. Today that requires N separate invocations.

Closes #2387.

# team on both the pipeline and job spans, one call
datadog-ci tag --level pipeline,job --tags team:backend
# job_maintainer on both job and step
datadog-ci tag --level job,step --tags job_maintainer:alice

Behavior

  • --level accepts one or more of [pipeline, job, stage, step] as a comma-separated list.
  • The full tag set is sent to each listed span — one request per level.
  • Duplicate levels are ignored; order is irrelevant (levels are processed by span depth).
  • Validation is fail-fast: an unknown or provider-unsupported member errors before anything is sent.
  • Single-level usage is unchanged, and so is --no-fail: it still tolerates a failed submission request but not setup/config errors (missing API key, unsupported provider, GitHub diagnostic logs that can't be located), which exit non-zero with the offending level named.

Implementation

  • A shared processLevels() helper drives the per-level loop for both commands; each level is enriched on its own copy of ciEnv so e.g. the step index never leaks into the job request.
  • A per-execution GithubLogCache locates and reads the GitHub Actions diagnostic logs at most once even when several levels need them (e.g. --level job,step). It is scoped to a single command run, never module-global, so it can't leak across commands or tests.
  • tag READMEs and CLI help updated.

Tests

  • parseLevels unit tests (single/multi/sort/dedupe/whitespace/empty/unknown/unsupported).
  • processLevels tests: per-execution caching (logs read once across job,step), orchestration-id selection cached, and fatal-error propagation annotated with the level.
  • Command tests for both tag: one request per level, dedupe, fail-fast, GitHub job,step enrichment, and --no-fail semantics.

yarn build, yarn lint, and the affected test suites pass.

-- Claudelie

🤖 Generated with Claude Code

@eliebleton-manomano
eliebleton-manomano requested review from a team as code owners June 26, 2026 17:20
@jeff-morgan-dd jeff-morgan-dd self-assigned this Jun 26, 2026
@Drarig29 Drarig29 added the software-delivery Related to [coverage, deployment, dora, junit, measure, tag, trace] label Jun 29, 2026
@DataDog DataDog deleted a comment from datadog-prod-us1-4 Bot Jun 29, 2026

@Drarig29 Drarig29 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM for tag, just a few nits.

But for measure, can you really think of a measure that would be interesting to set with the same value at multiple levels? It sounds like it's more of a feature for tag only 🤔

Numbers are meant to be aggregated, so I would expect this:

  • Pipeline: binary.size:1000
    • Job 1: binary.size:600
    • Job 2: binary.size:400

And since we market measures as "numerical tags", I'd assume we overwrite the values instead of appending. I'll check with the team.

But long story short, it looks like you are only interested for the tag command, so I'd say it's safer to split the effort... because it's indeed a low-hanging fruit on the tag side.

Comment thread packages/base/src/commands/tag/README.md Outdated
Comment thread packages/base/src/commands/tag/README.md
Comment thread packages/base/src/commands/tag/README.md Outdated
@Drarig29

Drarig29 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Also, I ran the CI and it's failing. You can run the tests locally with yarn test. And there is now a conflicting file.

Thanks again for the effort 🙏

eliebleton-manomano and others added 2 commits July 1, 2026 19:04
Allow `--level pipeline,job` so the same tags/measures are applied to
multiple span levels in one invocation. Levels are deduped and validated
fail-fast; one request is sent per level. Adds a shared per-level loop
(`processLevels`) used by both `tag` and `measure`, and a per-execution
cache so the GitHub Actions diagnostic logs are located and read once
even when several levels need them (e.g. `--level job,step`).

Single-level usage and `--no-fail` semantics are unchanged: `--no-fail`
still tolerates a failed submission but not setup/config errors, which
are reported with the offending level.

Refs DataDog#2387

Co-Authored-By: Claude Opus 4.8 <[email protected]>
These tests assumed the host filesystem lacks GitHub Worker_*.log
diagnostic files under the well-known fallback dirs to force the
`step` enrichment to fail. That assumption doesn't hold on real
GitHub Actions runners, causing flaky CI failures. Mock
fs.readdirSync to throw ENOENT explicitly instead.
…EADME

Reviewer feedback on DataDog#2388: measure semantics for multi-level are unclear
(should measures be aggregated/overwritten per level instead of duplicated?),
so revert measure back to single-level --level. tag keeps additive
comma-separated --level. Also applies 3 README wording nits for tag.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
@eliebleton-manomano

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review, @Drarig29!

  • Applied all 3 README nits on tag: {pipeline,job,stage,step} set notation, moved the level-selection explanation to its own paragraph, and reworded the additive blurb to emphasize it's multiple levels being targeted.
  • Dropped multi-level --level support from measure entirely (reverted to the original single-level behavior/README/tests). Agreed the additive-duplication semantics don't make sense for numeric measures — tag keeps the additive comma-separated --level, measure stays single-level only.
  • Also rebased on master and fixed the CI failures you flagged (a couple of tests were implicitly relying on the local filesystem not having stray Worker_*.log files, which didn't hold on the hosted runners).

-- Claudelie

@Drarig29 Drarig29 changed the title feat(tag,measure): additive comma-separated --level (e.g. --level pipeline,job) feat(tag): comma-separated --level (e.g. --level pipeline,job) Jul 2, 2026
@Drarig29
Drarig29 removed the request for review from GabrielAnca July 2, 2026 15:38
@Drarig29
Drarig29 merged commit 3bac124 into DataDog:master Jul 2, 2026
34 checks passed
@TalUsvyatsky TalUsvyatsky mentioned this pull request Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

software-delivery Related to [coverage, deployment, dora, junit, measure, tag, trace]

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(tag/measure): additive comma-separated --level (e.g. --level pipeline,job)

4 participants