Skip to content

fix: use exact YAML line matching for agent job detection in integration tests#25780

Merged
pelikhan merged 1 commit intomainfrom
copilot/fix-tests-again
Apr 11, 2026
Merged

fix: use exact YAML line matching for agent job detection in integration tests#25780
pelikhan merged 1 commit intomainfrom
copilot/fix-tests-again

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 11, 2026

Same class of bug fixed in #25778 — agent job extraction in integration tests uses strings.Index(content, "agent:") which matches container image references in YAML comments (e.g., ghcr.io/github/gh-aw-firewall/agent:0.25.18) instead of the actual job definition line.

Changes

  • checkout_optimization_test.go, trial_mode_test.go, local_action_permissions_test.go: Use "\n agent:\n" (or "\n " + jobName + ":\n") as the marker to find the exact YAML job line instead of a substring match
  • environment_test.go: Use line == " agent:" exact match instead of strings.Contains

Before:

agentJobStart := strings.Index(lockContentStr, "agent:")

After:

agentJobMarker := "\n  agent:\n"
markerIdx := strings.Index(lockContentStr, agentJobMarker)

…L line matching

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/592be6a0-7628-4748-8064-710d92bbac5e

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan pelikhan marked this pull request as ready for review April 11, 2026 10:48
Copilot AI review requested due to automatic review settings April 11, 2026 10:48
@pelikhan pelikhan merged commit 0569653 into main Apr 11, 2026
54 checks passed
@pelikhan pelikhan deleted the copilot/fix-tests-again branch April 11, 2026 10:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates integration tests to detect the agent (or other) job definitions using exact YAML job-line matching, avoiding false positives where agent: appears in YAML comments (e.g., container image tags).

Changes:

  • Switch job detection in multiple integration tests from substring matching to exact YAML job key markers (e.g., "\n agent:\n" / exact line equality).
  • Adjust job-section extraction logic to start from the matched job key line and stop at the next top-level job key.
Show a summary per file
File Description
pkg/workflow/trial_mode_test.go Uses an exact YAML job marker to extract the agent job section for token assertions.
pkg/workflow/local_action_permissions_test.go Uses an exact YAML job marker to locate and slice the target job section before validating permissions/checkout steps.
pkg/workflow/environment_test.go Changes agent job detection to exact line equality instead of substring matching.
pkg/workflow/checkout_optimization_test.go Uses an exact YAML job marker to bound the agent job section for checkout-step assertions.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

Comment on lines +149 to 156
// Extract the agent job section using exact YAML job marker
agentJobMarker := "\n agent:\n"
markerIdx := strings.Index(lockContentStr, agentJobMarker)
if markerIdx == -1 {
t.Fatalf("Agent job not found in compiled workflow")
}
agentJobStart := markerIdx + len("\n ") // point to "agent:\n"

Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

This test reimplements job-section extraction with manual string indexing and hard-coded offsets (e.g., len("\n ")). There is already an extractJobSection(yamlContent, jobName) helper in pkg/workflow/compiler_test_helpers_test.go that extracts a job by YAML indentation, which would simplify this logic and reduce brittleness if formatting changes.

See below for a potential fix:

				agentJobSection := extractJobSection(lockContentStr, "agent")
				if agentJobSection == "" {
					t.Fatalf("Agent job not found in compiled workflow")
				}

Copilot uses AI. Check for mistakes.
Comment on lines +137 to +146
// Extract the agent job section using exact YAML job marker
agentJobMarker := "\n agent:\n"
markerIdx := strings.Index(lockContent, agentJobMarker)
if markerIdx == -1 {
t.Error("Expected agent job in trial mode")
return
}

agentJobStart := markerIdx + len("\n ") // point to "agent:\n"

Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

The agent job section is extracted via a custom marker/index scan and magic offsets. Consider reusing the existing extractJobSection(yamlContent, jobName) helper from pkg/workflow/compiler_test_helpers_test.go to avoid duplicating YAML job-boundary logic and make the test less sensitive to minor formatting changes.

See below for a potential fix:

		agentJobSection := extractJobSection(lockContent, "agent")
		if agentJobSection == "" {
			t.Error("Expected agent job in trial mode")
			return
		}

Copilot uses AI. Check for mistakes.
Comment on lines +89 to 99
// Verify the job exists and extract using exact YAML job marker
jobMarker := "\n " + tt.jobName + ":\n"
markerIdx := strings.Index(lockContentStr, jobMarker)
if markerIdx == -1 {
t.Errorf("Expected %s job to be present", tt.jobName)
return
}

// Extract the job section
jobStart := strings.Index(lockContentStr, jobMarker)
if jobStart == -1 {
t.Fatalf("%s job not found in compiled workflow", tt.jobName)
}
jobStart := markerIdx + len("\n ") // point to "jobName:\n"

Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

This test duplicates YAML job extraction logic using string markers and manual scanning. There is an extractJobSection(yamlContent, jobName) helper in pkg/workflow/compiler_test_helpers_test.go that can extract tt.jobName's job body by indentation and would remove the need for the marker/index arithmetic here.

See below for a potential fix:

			// Verify the job exists and extract its YAML section using the shared helper.
			jobSection := extractJobSection(lockContentStr, tt.jobName)
			if jobSection == "" {
				t.Errorf("Expected %s job to be present", tt.jobName)
				return
			}

Copilot uses AI. Check for mistakes.
@github-actions github-actions Bot mentioned this pull request Apr 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 95/100

Excellent test quality

Metric Value
New/modified tests analyzed 4 (modified only — no new Test* functions added)
✅ Design tests (behavioral contracts) 4 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 4 (100%)
Duplicate test clusters 0
Test inflation detected No (net −8 lines across all test files; no production files changed)
🚨 Coding-guideline violations 0

What This PR Does

All four files are modified (not newly created). The PR refactors the agent job section detection in integration tests from a fragile substring search to an exact YAML job-line match:

Before After
strings.Index(lockContentStr, "agent:") — matches anywhere the word "agent:" appears in the YAML "\n agent:\n" — exact top-level YAML job marker
strings.Contains(line, AgentJobName+":") — could match step names, env vars, etc. line == agentJobLine — exact full-line equality

This is a correctness improvement: the old approach could produce a false-positive "agent job found" match if any step or key within another job contained the string "agent:". The new approach anchors on the precise YAML structure expected from the compiler.


Test Classification Details

Test File Classification Notes
TestCheckoutOptimization pkg/workflow/checkout_optimization_test.go ✅ Design Verifies checkout step inclusion/exclusion in agent job based on frontmatter; table-driven; multiple error paths via t.Fatalf/t.Errorf
TestEnvironmentSupport pkg/workflow/environment_test.go ✅ Design Verifies environment: block appears in correct YAML job; uses t.Errorf on mismatches
TestLocalActionPermissions pkg/workflow/local_action_permissions_test.go ✅ Design Verifies contents: read permission is injected in local-action dev mode; table-driven; multiple error paths
TestTrialModeCompilation pkg/workflow/trial_mode_test.go ✅ Design Verifies trial mode suppresses safe outputs and injects checkout token; uses t.Run subtests for Normal/Trial modes

Observations (Non-Blocking)

i️ Pre-existing redundant assertion in TestTrialModeCompilation (not introduced by this PR)

pkg/workflow/trial_mode_test.go lines ~70–74 and ~129–134 contain a copy-paste redundancy where the same condition is checked twice with different error messages:

// Both assertions check the EXACT same thing:
if !strings.Contains(lockContent, "safe_outputs:") {
    t.Error("Expected create_pull_request job in normal mode")
}
if !strings.Contains(lockContent, "safe_outputs:") {
    t.Error("Expected safe_outputs job in normal mode")
}

The second check is unreachable if the first fails and identical if it passes. This was pre-existing before this PR and is not introduced here, but it's worth cleaning up in a follow-up to avoid confusing error messages.


Language Support

Tests analyzed:

  • 🐹 Go (*_test.go): 4 tests — all integration (//go:build integration) ✅
  • 🟨 JavaScript (*.test.cjs, *.test.js): 0 tests changed

Verdict

Check passed. 0% of modified tests are implementation tests (threshold: 30%). All changes improve the accuracy of behavioral assertions by using exact YAML structure matching. No coding-guideline violations detected.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

🧪 Test quality analysis by Test Quality Sentinel · ● 1.2M ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 95/100. Test quality is excellent — 0% of modified tests are implementation tests (threshold: 30%). All 4 changed test functions are behavioral integration tests that verify the compiler's observable YAML output. The changes improve assertion accuracy by using exact YAML job-line matching instead of substring search.

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.

3 participants