Skip to content

Add test-rules command and CI workflow#191

Merged
whitemerch merged 3 commits into
mainfrom
chakib.hamie/backend_test_ci
Jun 16, 2026
Merged

Add test-rules command and CI workflow#191
whitemerch merged 3 commits into
mainfrom
chakib.hamie/backend_test_ci

Conversation

@whitemerch

@whitemerch whitemerch commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Motivation

When the scanner engine changes, there is no automated way to verify that existing rules still produce the expected findings. The rule test fixtures live in the default-rules repository and are now also stored in the backend API (alongside the rules themselves). This PR wires up the scanner to fetch and run those tests, so every PR gets a signal that the engine has not regressed against the full default rule suite.

Changes

API client

The Client interface gains a GetDefaultRulesetWithTests method that calls the same endpoint as GetDefaultRuleset but with include_tests=true. Three new types mirror the backend model: RuleTests, TestFile, and TestFinding. The Rule struct gains a Tests *RuleTests field that is populated when tests are requested.

test-rules command

A new test-rules subcommand fetches the default ruleset (with tests) from the Datadog API, materialises each rule's fixture files into a temporary directory, and runs the scanner engine against them. Positive fixtures are compared against the stored expected findings; negative fixtures must produce no findings. The command exits non-zero if any rule fails, prints a per-rule pass/fail summary, and accepts --type and --rule flags to scope the run to a subset of platforms or rules.

The rule is converted to a QueryMetadata via a JSON:API round-trip through the scanner's own datadog.Rule type, meaning the test exercises the exact same rule representation the scanner uses in production.

CI workflow

.github/workflows/test-rules.yml runs the command on every pull request targeting main and on every push to main. It requires DD_API_KEY and DD_APP_KEY repository secrets. Fork pull requests will pass vacuously since secrets are not available in that context.

QA Instruction

CI should pass

Impact

Adds a new CLI subcommand (test-rules) and a CI workflow. No changes to scan behaviour, output formats, or existing commands.

@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Jun 16, 2026

Copy link
Copy Markdown

🎯 Code Coverage (details)
Patch Coverage: 66.67%
Overall Coverage: 48.33% (+0.00%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 65c6531 | Docs | Datadog PR Page | Give us feedback!

@whitemerch
whitemerch force-pushed the chakib.hamie/backend_test_ci branch from b3e4410 to fc498c2 Compare June 16, 2026 08:30
@whitemerch
whitemerch marked this pull request as ready for review June 16, 2026 08:39
@whitemerch
whitemerch requested a review from a team as a code owner June 16, 2026 08:39
chatgpt-codex-connector[bot]

This comment was marked as resolved.

@whitemerch
whitemerch force-pushed the chakib.hamie/backend_test_ci branch 2 times, most recently from 4b420ec to b01db3b Compare June 16, 2026 09:10
@whitemerch
whitemerch force-pushed the chakib.hamie/backend_test_ci branch from b01db3b to 7e686fd Compare June 16, 2026 09:18
Comment thread .github/workflows/test-rules.yml Outdated
# Runs the scanner's engine against the rule fixtures stored in the Datadog
# backend. This catches engine regressions that break existing rule tests.
#
# Requires DD_API_KEY and DD_APP_KEY repository secrets (and optionally

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.

Remove the DD_API_KEY and DD_APP_KEY and DD_SITE. They are not required for the default rules and avoids problems with forks and external PRs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I always confuse the config file and the rules aahhh

Comment thread .gitignore
module_support

# local scanner binary
/scanner

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.

What's this one for?

@whitemerch whitemerch Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It prevents accidentally committing a locally-built binary. I ran go build ./cmd/scanner locally which dropped scanner in the root, and ended up committing it by accident

Comment thread pkg/datadog/client.go Outdated
Comment thread cmd/scanner/test_rules.go Outdated
Comment thread cmd/scanner/test_rules.go Outdated
Comment on lines +217 to +218
platformStr := rule.Platform
resourcePlatforms := testResourcePlatformsFor(platformStr)

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.

Suggested change
platformStr := rule.Platform
resourcePlatforms := testResourcePlatformsFor(platformStr)
resourcePlatforms := testResourcePlatformsFor(rule.Platform)

Also, are these supposed to be the platforms in the rule, or the platforms specified in the command line? Because my original test code uses the command line, and the validateResultShape function then uses resourcePlatforms to ...

I'm not sure that resourcePlatforms is needed at all! It only checks that the rule's platform is in resourcePlatforms and, if so, it does extra checks. It doesn't fail anything if it's not there. But the platform is going to be in resourcePlatforms whether we use the command line or the rule's platform, so it's irrelevant. Can you have a look?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I removed resourcePlatforms entirely safely

Comment thread cmd/scanner/test_rules.go Outdated
// testResourcePlatformsFor returns the set of platforms that require resourceType/resourceName.
// Mirrors the logic used in the default-rules test tool.
func testResourcePlatformsFor(platform string) map[string]struct{} {
resourcePlatforms := map[string]struct{}{

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.

So, all of them?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed it, now it will directly look at platformsRequiringResourceKeys

Comment thread cmd/scanner/test_rules.go Outdated
Comment thread cmd/scanner/test_rules.go
@@ -0,0 +1,518 @@
package main

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.

Suggestion (not necessarily for this PR): put the code that runs tests in a separate package, and then we can import it from the default-rules repo and use it there without having two copies of the same test code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I will follow up in another PR

Comment thread .github/workflows/test-rules.yml Outdated
Comment thread cmd/scanner/test_rules.go Outdated
jacobotb
jacobotb previously approved these changes Jun 16, 2026
@whitemerch
whitemerch merged commit 83f8764 into main Jun 16, 2026
19 of 20 checks passed
@whitemerch
whitemerch deleted the chakib.hamie/backend_test_ci branch June 16, 2026 16:17
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.

2 participants