Skip to content

Add include_all label scope to GitOps and fleetctl (#41566) - #44534

Merged
juan-fdz-hawa merged 5 commits into
mainfrom
41566-policyreport-labels-gitops
May 5, 2026
Merged

Add include_all label scope to GitOps and fleetctl (#41566)#44534
juan-fdz-hawa merged 5 commits into
mainfrom
41566-policyreport-labels-gitops

Conversation

@juan-fdz-hawa

@juan-fdz-hawa juan-fdz-hawa commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Related issue: Resolves #41566

Wires labels_include_all to GitOps and fleetctl for policies and reports.

Checklist for submitter

If some of the following don't apply, delete the relevant line.

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • New Features

    • Added "include all labels" (labels_include_all) support for queries and policies; CLI, GitOps exports, and API specs now serialize both include-any and include-all.
  • Bug Fixes / Behavior

    • Policy application and membership cleanup now respect include-all criteria.
    • Host report listing now correctly filters queries by include-all vs include-any and enforces premium gating for include-all.
  • Tests

    • Added unit and integration tests covering serialization, GitOps validation, premium gating, repo/generate GitOps exports, and batch/spec rejection.

@juan-fdz-hawa

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@juan-fdz-hawa juan-fdz-hawa changed the title Add include_all label scope to GitOps and fleetctl Add include_all label scope to GitOps and fleetctl (#41566) Apr 30, 2026
@coderabbitai

coderabbitai Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new labels_include_all label scope for policies and queries across CLI (fleetctl), GitOps generation/parsing, service API, and datastore layers. Changes include new exported fields on QuerySpec and PolicySpec, spec-level Verify validation enforcing mutual exclusivity of label scopes, premium license gating for labels_include_all at service and GitOps entrypoints, serialization/deserialization and GitOps YAML/JSON generation for labels_include_all, datastore persistence and policy membership updates for include-all, SQL filtering for host reports to support require-all, helper conversion functions, and unit and integration tests.

Possibly related PRs

  • fleetdm/fleet#44305: Implements labels_include_all support across policies/queries including API structs, datastore persistence, service validation, and tests — directly overlaps on the same feature.
  • fleetdm/fleet#43420: Modifies ApplyPolicySpecs in server/datastore/mysql/policies.go — related to this PR’s changes that add LabelsIncludeAll handling in ApplyPolicySpecs.
  • fleetdm/fleet#37801: Touches gitops label-processing logic in cmd/fleetctl/fleetctl/gitops.go, overlapping with this PR’s GitOps label-scope handling.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding include_all label scope support to GitOps and fleetctl for policies and reports.
Description check ✅ Passed The PR description addresses the related issue (#41566), provides context about the change (wiring labels_include_all to GitOps/fleetctl), and checks the required boxes for changes file and automated tests.
Linked Issues check ✅ Passed The PR fully addresses all three objectives from issue #41566: LabelsIncludeAll added to policy/query specs [multiple files], mutual exclusion validation enforced in GitOps [gitops.go/gitops_test.go], and labels_include_all included in generated YAML [generate_gitops.go and testdata files].
Out of Scope Changes check ✅ Passed All changes are within scope: spec field additions, validation logic, GitOps/fleetctl integration, test coverage, and YAML generation directly support the stated objectives with no unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 41566-policyreport-labels-gitops

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (5)
changes/41566-policy-report-labels-gitops (1)

1-1: ⚡ Quick win

Use user-facing language in the changelog entry.

The word "Wires" is developer jargon that doesn't clearly communicate the user-visible change. Changelog entries should describe what users can now do, not implementation details.

📝 Suggested rewording for clarity
-- Wires labels_include_all to GitOps/fleetctl for policies and reports.
+- Added support for `labels_include_all` label scope in GitOps and fleetctl for policies and reports.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@changes/41566-policy-report-labels-gitops` at line 1, Change the changelog
entry that currently reads "Wires labels_include_all to GitOps/fleetctl for
policies and reports" to user-facing language that describes the new capability;
for example, replace "Wires" with a clear phrase such as "Add support for" or
"Allow users to include" so the entry reads like "Add support for
labels_include_all in GitOps/fleetctl for policies and reports" (referencing the
labels_include_all flag, GitOps/fleetctl integration, and the policies and
reports feature to locate the entry).
cmd/fleetctl/fleetctl/get_test.go (1)

1891-1945: ⚡ Quick win

Add one default table-output assertion for labels_include_all.

These tests cover --yaml/--json, but the table behavior added at Line 352 in cmd/fleetctl/fleetctl/get.go isn’t exercised yet. A plain fleetctl get reports assertion for labels_include_all would close that gap.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/fleetctl/fleetctl/get_test.go` around lines 1891 - 1945,
TestGetReportsLabelsIncludeAll currently asserts only YAML/JSON outputs but not
the default table output; add a table-output assertion by calling
RunAppForTest(t, []string{"get", "reports"}) and asserting the returned string
contains the labels (e.g. assert.Contains(t, out, "labelA") and
assert.Contains(t, out, "labelB") or a combined "labelA,labelB" as appropriate)
so the new table formatting in the get reports command is exercised; update
TestGetReportsLabelsIncludeAll to include these assert calls referencing
RunAppForTest and the "get reports" invocation.
server/service/queries.go (1)

824-827: ⚡ Quick win

Return the missing label names here.

label not found is too generic now that both labels_include_any and labels_include_all funnel through this branch. Including the missing names would make GitOps/API failures much easier to fix.

Suggested change
-		for _, name := range allLabelNames {
-			if _, ok := labelsMap[name]; !ok {
-				return nil, ctxerr.New(ctx, "label not found")
-			}
-		}
+		missing := make([]string, 0)
+		for _, name := range allLabelNames {
+			if _, ok := labelsMap[name]; !ok {
+				missing = append(missing, name)
+			}
+		}
+		if len(missing) > 0 {
+			return nil, ctxerr.New(ctx, fmt.Sprintf("labels not found: %s", strings.Join(missing, ", ")))
+		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/service/queries.go` around lines 824 - 827, The loop over
allLabelNames that currently returns a generic ctxerr.New(ctx, "label not
found") should collect the actual missing label names (e.g., build a slice
missing := []string{} when iterating for _, name := range allLabelNames and
checking labelsMap[name]) and return an error that includes them (e.g., fmt.Join
or formatted message) instead of the generic string; update the return to use
ctxerr.Newf or ctxerr.New with a formatted message like "labels not found:
<names>" so callers of the function that contains this loop (the block using
labelsMap and allLabelNames) get the specific missing label names.
cmd/fleetctl/fleetctl/gitops_test.go (1)

295-334: ⚡ Quick win

Add a free-tier labels_include_all GitOps test.

These new cases only exercise labels_include_all with a premium license. The existing free-tier coverage still only protects labels_include_any, so the new license-gated branch can regress without a failing test.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/fleetctl/fleetctl/gitops_test.go` around lines 295 - 334, Add a new test
function (e.g., TestGitOpsQueryLabelsIncludeAllFreeTier) that mirrors
TestGitOpsQueryLabelsIncludeAllUnknownLabel but sets the license to
fleet.TierFree (use RunServerWithMockedDS/TestServerOpts like the existing
test), creates the same GitOps YAML that uses labels_include_all, calls
RunAppNoChecks with that file, and assert that it errors and the error message
mentions the license/gating of labels_include_all (check Error and ErrorContains
against text including "labels_include_all" and "license" or "premium"). This
ensures the labels_include_all license-gated branch is covered; reference the
existing TestGitOpsQueryLabelsIncludeAllUnknownLabel, labels_include_all,
RunServerWithMockedDS, and RunAppNoChecks to locate where to add the duplicate
test.
server/service/integration_enterprise_test.go (1)

29473-29493: ⚡ Quick win

Add explicit non-persistence assertions for rejected single-spec GitOps requests

These negative tests currently validate only the error response. Please also assert the rejected policy/query names were not created, so partial-write regressions are caught (same guarantee you already enforce in the batch test).

Also applies to: 29589-29599

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/service/integration_enterprise_test.go` around lines 29473 - 29493,
Add explicit assertions that the rejected spec names were not persisted: after
each POST that returns BadRequest (the requests captured in rejSpecResp and
rejSpecResp2 sent with fleet.ApplyPolicySpecsRequest containing fleet.PolicySpec
named "spec-rej-any-"+t.Name() and "spec-rej-excl-"+t.Name()), call the API to
fetch specs (e.g., via s.Do GET /api/latest/fleet/spec/policies or the
single-spec read endpoint) and assert the returned list does not contain those
policy names; use the same helper extractServerErrorText and compare against the
PolicySpec.Name values and fleet.ErrPolicyConflictingLabels to ensure no partial
write occurred.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@changes/41566-policy-report-labels-gitops`:
- Line 1: Change the changelog entry that currently reads "Wires
labels_include_all to GitOps/fleetctl for policies and reports" to user-facing
language that describes the new capability; for example, replace "Wires" with a
clear phrase such as "Add support for" or "Allow users to include" so the entry
reads like "Add support for labels_include_all in GitOps/fleetctl for policies
and reports" (referencing the labels_include_all flag, GitOps/fleetctl
integration, and the policies and reports feature to locate the entry).

In `@cmd/fleetctl/fleetctl/get_test.go`:
- Around line 1891-1945: TestGetReportsLabelsIncludeAll currently asserts only
YAML/JSON outputs but not the default table output; add a table-output assertion
by calling RunAppForTest(t, []string{"get", "reports"}) and asserting the
returned string contains the labels (e.g. assert.Contains(t, out, "labelA") and
assert.Contains(t, out, "labelB") or a combined "labelA,labelB" as appropriate)
so the new table formatting in the get reports command is exercised; update
TestGetReportsLabelsIncludeAll to include these assert calls referencing
RunAppForTest and the "get reports" invocation.

In `@cmd/fleetctl/fleetctl/gitops_test.go`:
- Around line 295-334: Add a new test function (e.g.,
TestGitOpsQueryLabelsIncludeAllFreeTier) that mirrors
TestGitOpsQueryLabelsIncludeAllUnknownLabel but sets the license to
fleet.TierFree (use RunServerWithMockedDS/TestServerOpts like the existing
test), creates the same GitOps YAML that uses labels_include_all, calls
RunAppNoChecks with that file, and assert that it errors and the error message
mentions the license/gating of labels_include_all (check Error and ErrorContains
against text including "labels_include_all" and "license" or "premium"). This
ensures the labels_include_all license-gated branch is covered; reference the
existing TestGitOpsQueryLabelsIncludeAllUnknownLabel, labels_include_all,
RunServerWithMockedDS, and RunAppNoChecks to locate where to add the duplicate
test.

In `@server/service/integration_enterprise_test.go`:
- Around line 29473-29493: Add explicit assertions that the rejected spec names
were not persisted: after each POST that returns BadRequest (the requests
captured in rejSpecResp and rejSpecResp2 sent with fleet.ApplyPolicySpecsRequest
containing fleet.PolicySpec named "spec-rej-any-"+t.Name() and
"spec-rej-excl-"+t.Name()), call the API to fetch specs (e.g., via s.Do GET
/api/latest/fleet/spec/policies or the single-spec read endpoint) and assert the
returned list does not contain those policy names; use the same helper
extractServerErrorText and compare against the PolicySpec.Name values and
fleet.ErrPolicyConflictingLabels to ensure no partial write occurred.

In `@server/service/queries.go`:
- Around line 824-827: The loop over allLabelNames that currently returns a
generic ctxerr.New(ctx, "label not found") should collect the actual missing
label names (e.g., build a slice missing := []string{} when iterating for _,
name := range allLabelNames and checking labelsMap[name]) and return an error
that includes them (e.g., fmt.Join or formatted message) instead of the generic
string; update the return to use ctxerr.Newf or ctxerr.New with a formatted
message like "labels not found: <names>" so callers of the function that
contains this loop (the block using labelsMap and allLabelNames) get the
specific missing label names.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 86db80c1-58bc-4b6d-91b0-7cc95e932b01

📥 Commits

Reviewing files that changed from the base of the PR and between f70a02a and 6a694b3118cae68f425c18b03c4958b1a0efb636.

📒 Files selected for processing (13)
  • changes/41566-policy-report-labels-gitops
  • cmd/fleetctl/fleetctl/get.go
  • cmd/fleetctl/fleetctl/get_test.go
  • cmd/fleetctl/fleetctl/gitops.go
  • cmd/fleetctl/fleetctl/gitops_test.go
  • server/datastore/mysql/policies.go
  • server/datastore/mysql/policies_test.go
  • server/fleet/policies.go
  • server/fleet/queries.go
  • server/service/global_policies.go
  • server/service/integration_core_test.go
  • server/service/integration_enterprise_test.go
  • server/service/queries.go

@codecov

codecov Bot commented Apr 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.65306% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.67%. Comparing base (575a42b) to head (bc98a3f).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
server/service/queries.go 58.33% 8 Missing and 2 partials ⚠️
cmd/fleetctl/fleetctl/get.go 33.33% 3 Missing and 1 partial ⚠️
cmd/fleetctl/fleetctl/gitops.go 85.71% 2 Missing ⚠️
cmd/fleetctl/fleetctl/generate_gitops.go 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #44534      +/-   ##
==========================================
- Coverage   66.68%   66.67%   -0.02%     
==========================================
  Files        2664     2664              
  Lines      214602   214653      +51     
  Branches     9839     9839              
==========================================
+ Hits       143112   143123      +11     
- Misses      58470    58502      +32     
- Partials    13020    13028       +8     
Flag Coverage Δ
backend 68.55% <82.65%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@juan-fdz-hawa
juan-fdz-hawa force-pushed the 41566-policyreport-labels-gitops branch from 6a694b3 to d59fe27 Compare May 1, 2026 11:31
@juan-fdz-hawa
juan-fdz-hawa marked this pull request as ready for review May 1, 2026 11:36
@juan-fdz-hawa
juan-fdz-hawa requested a review from a team as a code owner May 1, 2026 11:36

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/service/queries.go`:
- Around line 711-728: Reject nil/malformed query specs before dereferencing
them: in the loops that iterate over specs (the pre-license premium check and
the subsequent conversion loop that calls spec.Verify()), first check for spec
== nil and if so call setAuthCheckedOnPreAuthErr(ctx) and return a
fleet.BadRequestError (via ctxerr.Wrap with a message like "invalid query spec:
nil"). Ensure both places reference the same behavior so no nil dereference
occurs in the license check (where LabelsIncludeAny/All are read) and before
calling spec.Verify().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 08d3b968-9bea-4132-8b72-c763c8718142

📥 Commits

Reviewing files that changed from the base of the PR and between 6a694b3118cae68f425c18b03c4958b1a0efb636 and d59fe27.

📒 Files selected for processing (14)
  • changes/41566-policy-report-labels-gitops
  • cmd/fleetctl/fleetctl/get.go
  • cmd/fleetctl/fleetctl/get_test.go
  • cmd/fleetctl/fleetctl/gitops.go
  • cmd/fleetctl/fleetctl/gitops_test.go
  • server/datastore/mysql/policies.go
  • server/datastore/mysql/policies_test.go
  • server/fleet/labels.go
  • server/fleet/policies.go
  • server/fleet/queries.go
  • server/service/global_policies.go
  • server/service/integration_core_test.go
  • server/service/integration_enterprise_test.go
  • server/service/queries.go
✅ Files skipped from review due to trivial changes (2)
  • changes/41566-policy-report-labels-gitops
  • cmd/fleetctl/fleetctl/get_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • server/fleet/policies.go
  • cmd/fleetctl/fleetctl/get.go
  • cmd/fleetctl/fleetctl/gitops.go
  • cmd/fleetctl/fleetctl/gitops_test.go

Comment thread server/service/queries.go Outdated
nulmete
nulmete previously approved these changes May 4, 2026

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
server/service/integration_enterprise_test.go (1)

29458-29471: ⚡ Quick win

Assert the exact label set, not just the count.

These checks would still pass if the wrong labels were persisted or if the same label appeared twice. Verifying the actual label names/IDs here would make the new coverage catch mapping regressions instead of only cardinality regressions. The same tightening applies to the similar Len(...) assertions in the batch-success case.

Also applies to: 29581-29588, 29764-29775

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/service/integration_enterprise_test.go` around lines 29458 - 29471,
The test currently only asserts counts for
specPolicy.LabelsIncludeAll/LabelsIncludeAny/LabelsExcludeAny which can miss
wrong or duplicate labels; update the assertions to verify the exact label
contents (e.g., compare the expected label names/IDs against
specPolicy.LabelsIncludeAll using an unordered comparison like ElementsMatch or
by sorting then Equal) and do the same tightening for the other occurrences
noted (the batch-success checks around the other ranges); locate checks
referencing s.ds.ListGlobalPolicies, the specPolicy variable and the struct
fields LabelsIncludeAll/LabelsIncludeAny/LabelsExcludeAny to make these
replacements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@server/service/integration_enterprise_test.go`:
- Around line 29458-29471: The test currently only asserts counts for
specPolicy.LabelsIncludeAll/LabelsIncludeAny/LabelsExcludeAny which can miss
wrong or duplicate labels; update the assertions to verify the exact label
contents (e.g., compare the expected label names/IDs against
specPolicy.LabelsIncludeAll using an unordered comparison like ElementsMatch or
by sorting then Equal) and do the same tightening for the other occurrences
noted (the batch-success checks around the other ranges); locate checks
referencing s.ds.ListGlobalPolicies, the specPolicy variable and the struct
fields LabelsIncludeAll/LabelsIncludeAny/LabelsExcludeAny to make these
replacements.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ba7dad56-2e04-4d14-adf8-27d7677c9439

📥 Commits

Reviewing files that changed from the base of the PR and between 0e9e38a8dc91494dbbe9ea3d0606a8a46e1ddc59 and 6daa27464e4fe6c9ed6812f6aaf34933264c6890.

📒 Files selected for processing (4)
  • server/datastore/mysql/query_results.go
  • server/datastore/mysql/query_results_test.go
  • server/service/integration_core_test.go
  • server/service/integration_enterprise_test.go

nulmete
nulmete previously approved these changes May 5, 2026
Resolves #41566

Wires labels_include_all to GitOps and fleetctl for policies and reports.
@juan-fdz-hawa
juan-fdz-hawa force-pushed the 41566-policyreport-labels-gitops branch from 0e8f5ba to bc98a3f Compare May 5, 2026 17:32
@juan-fdz-hawa
juan-fdz-hawa merged commit 7088dfa into main May 5, 2026
59 checks passed
@juan-fdz-hawa
juan-fdz-hawa deleted the 41566-policyreport-labels-gitops branch May 5, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Policy/report labels: GitOps

2 participants