Skip to content

Improve actionpins internal test coverage for fallback and pin-resolution edge cases#42834

Merged
pelikhan merged 7 commits into
mainfrom
copilot/testify-expert-improve-test-quality
Jul 2, 2026
Merged

Improve actionpins internal test coverage for fallback and pin-resolution edge cases#42834
pelikhan merged 7 commits into
mainfrom
copilot/testify-expert-improve-test-quality

Conversation

Copilot AI commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

This updates pkg/actionpins/actionpins_internal_test.go to cover previously untested resolution branches and edge cases in pkg/actionpins/actionpins.go, with emphasis on semver fallback behavior, exact-match resolution, and warning dedup semantics.

  • findCompatiblePin semver fallback coverage

    • Added TestFindCompatiblePin_SemverFallback for:
      • exact-major compatibility (v5 → highest compatible v5.x)
      • exact-version match
      • no compatible match
      • empty requested version
  • Non-strict hardcoded fallback behavior

    • Added TestResolveNonStrictHardcodedPin_CompatibleAndFallback covering:
      • compatible selection path
      • highest-available fallback path when no compatible version exists
      • warning dedup across repeated calls for the same cache key
      • stderr warning emission assertions (including single-emission expectation)
  • Exact hardcoded resolution branches

    • Added TestResolveExactHardcodedPin_ByVersion
    • Added TestResolveExactHardcodedPin_NoMatch
  • Container pin tests refactor

    • Consolidated MCP gateway version-specific tests into one table-driven test:
      • TestGetContainerPin_MCPGatewayVersionsArePinned
  • Mismatch counting boundary expansion

    • Expanded TestCountPinKeyMismatches_ReturnsOnlyVersionMismatches with subtests for:
      • empty input
      • zero mismatches
      • invalid key format (no @version)
      • mixed valid/invalid entries with a single real mismatch
  • Assertion clarity cleanup

    • Replaced zero-count equality assertion with assert.Zero in SHA-skip dynamic resolution test.
t.Run("falls back to highest available pin and deduplicates warnings", func(t *testing.T) {
	ctx := &PinContext{Warnings: make(map[string]bool)}
	expectedWarning := "Unable to resolve actions/checkout@v9 dynamically, using hardcoded pin for actions/checkout@v5.2.0"

	stderrOutput := testutil.CaptureStderr(t, func() {
		_ = resolveNonStrictHardcodedPin("actions/checkout", "v9", pins, ctx)
		_ = resolveNonStrictHardcodedPin("actions/checkout", "v9", pins, ctx)
	})

	assert.Equal(t, 1, strings.Count(stderrOutput, expectedWarning))
	assert.Len(t, ctx.Warnings, 1)
})

Generated by 👨‍🍳 PR Sous Chef · 8.66 AIC · ⌖ 21.3 AIC · ⊞ 6.4K ·


Generated by 👨‍🍳 PR Sous Chef · 10.5 AIC · ⌖ 16.1 AIC · ⊞ 6.4K ·

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve test quality in pkg/actionpins/actionpins_internal_test.go Improve actionpins internal test coverage for fallback and pin-resolution edge cases Jul 1, 2026
Copilot AI requested a review from pelikhan July 1, 2026 20:38
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Hey @Copilot 👋 — great work expanding coverage for the actionpins package! The additions here — semver fallback paths, exact-match resolution branches, warning dedup semantics, and the table-driven MCP gateway version test — are exactly the kind of edge-case coverage that prevents regressions in pin resolution logic.

The PR is tightly scoped to a single test file, the description is thorough and well-structured, and no new dependencies are introduced. This looks ready for review. 🚀

Generated by ✅ Contribution Check · 107.8 AIC · ⌖ 14.7 AIC · ⊞ 6.3K ·

@pelikhan pelikhan marked this pull request as ready for review July 2, 2026 00:57
Copilot AI review requested due to automatic review settings July 2, 2026 00:57

Copilot AI 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.

Pull request overview

This pull request expands and clarifies the internal unit test coverage for pkg/actionpins/actionpins.go, focusing on semver-compatible fallback selection, exact hardcoded pin resolution, warning deduplication behavior, and a few additional edge cases around pin-key mismatch counting.

Changes:

  • Added new/expanded tests covering findCompatiblePin, resolveNonStrictHardcodedPin, and additional resolveExactHardcodedPin branches (by version + no match).
  • Refactored MCP gateway container pin assertions into a single table-driven test.
  • Expanded countPinKeyMismatches test coverage with subtests for empty input, all-matching input, invalid key format, and mixed entries; plus a small assertion cleanup (assert.Zero).
Show a summary per file
File Description
pkg/actionpins/actionpins_internal_test.go Adds broader internal test coverage for action pin fallback, exact-match resolution, warning deduplication, container pinning, and mismatch counting edge cases.

Review details

Tip

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

  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Low

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer failed during the skills-based review.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Code Quality Reviewer failed during code quality review.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (170 new lines in pkg/actionpins/) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/42834-table-driven-subtests-for-actionpins-pin-resolution.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI could not infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-42834: Table-Driven Subtests for actionpins Pin-Resolution Coverage

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 42834-table-driven-subtests-for-actionpins-pin-resolution.md for PR #42834).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · 39.4 AIC · ⌖ 9.69 AIC · ⊞ 8.4K ·
Comment /review to run again

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

⚠️ Test Quality Score: 78/100 — Acceptable

Analyzed 21 test(s): 20 design, 1 implementation, 0 violation(s).

📊 Metrics (21 tests)
Metric Value
Analyzed 21 (Go: 21, JS: 0)
✅ Design 20 (95%)
⚠️ Implementation 1 (5%)
Edge/error coverage 14 (67%)
Duplicate clusters 0
Inflation YES (170 test lines added, 0 production lines added)
🚨 Violations 0
Test File Classification Issues
TestBuildByRepoIndex_GroupsByRepoAndSortsDescending actionpins_internal_test.go:16 design_test None
TestCountPinKeyMismatches_ReturnsOnlyVersionMismatches :35 design_test None
TestInitWarnings_InitializesAndPreservesMap :65 design_test None
TestFormatPinnedActionWithResolution_ConsistentVersionComment :92 design_test Subtest loop missing assertion messages (lines 130)
TestFindCompatiblePin_SemverFallback :135 design_test Loop body assertions lack failure context (lines 183–188)
TestFindVersionBySHA_ReturnsVersionForKnownSHA :194 design_test None
TestGetContainerPin_ReturnsPinnedImage :215 design_test Happy-path only
TestGetContainerPin_MCPGatewayVersionsArePinned :223 implementation_test Hardcodes specific SHA digests; brittle on embed updates
TestGetContainerPin_DefaultMCPImagesArePinned :252 design_test None
TestResolveActionPinDynamically_SkipsForSHAInput :276 design_test None
TestResolveActionPinFromHardcodedPins_StrictModeNoFallback :292 design_test None
TestResolveExactHardcodedPin_BySHA :301 design_test None
TestResolveExactHardcodedPin_ByVersion :310 design_test None
TestResolveExactHardcodedPin_NoMatch :320 design_test None
TestResolveNonStrictHardcodedPin_CompatibleAndFallback :329 design_test None
TestResolveActionPinFromHardcodedPins_SkipHardcodedFallback :368 design_test None
TestApplyActionPinMapping_NoMapping :390 design_test None
TestApplyActionPinMapping_AppliesMapping :399 design_test None
TestApplyActionPinMapping_OnlyMatchesExact :413 design_test None
TestApplyActionPinMapping_DeduplicatesInfoMessage :428 design_test None
TestApplyActionPinMapping_InvalidMappingValueSkipped :451 design_test None
⚠️ Flagged Tests (3)

TestGetContainerPin_MCPGatewayVersionsArePinned (actionpins_internal_test.go:223) — implementation_test. Hardcodes specific SHA digests (e.g. sha256:2bb8..., sha256:6482...) for two versioned MCP gateway images. This test will silently break any time the embedded action_pins.json is updated for those images, providing no signal about behavioral contracts — it only verifies that the JSON file has a specific byte sequence. Consider replacing hardcoded digests with a behavioral assertion (e.g. digest is non-empty and PinnedImage ends with the digest).

TestFormatPinnedActionWithResolution_ConsistentVersionComment (actionpins_internal_test.go:127–131) — design_test, minor issue. The inner assert.Equal at line 130 omits a failure message. If a subtest fails the error will read Not equal: ... with no indication of which case failed or why. Add a descriptive message: assert.Equal(t, tt.expected, result, "case %q: unexpected formatted output", tt.name).

TestFindCompatiblePin_SemverFallback (actionpins_internal_test.go:180–191) — design_test, minor issue. Assertions inside the t.Run loop at lines 183–188 omit failure messages. When a subtest fails, the error context is lost. Add tt.name as a message argument to each assertion.

Verdict

Passed. 5% implementation tests (threshold: 30%). No guideline violations (no forbidden mocks, required build tag //go:build !integration present). Minor: two table-driven tests omit assertion failure messages in their loop bodies, and one test hardcodes SHA digests making it brittle to embed updates. Test inflation flag is expected for a tests-only PR.

References: §28557910722

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel · 94.6 AIC · ⌖ 19.6 AIC · ⊞ 6.8K ·
Comment /review to run again

@github-actions github-actions 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.

✅ Test Quality Sentinel: 78/100. 5% implementation tests (threshold: 30%). No guideline violations.

@github-actions github-actions 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.

Review: Improve actionpins internal test coverage

Good quality test addition overall — coverage of fallback paths, warning deduplication, and boundary expansion for countPinKeyMismatches all look correct. A few observations:

Correctness ✅

  • All new assertions match the actual implementation logic in actionpins.go.
  • Warning dedup test correctly captures that the ctx.Warnings map and stderr emission are both deduplicated on the same cacheKey.
  • The empty-version/no-match cases for findCompatiblePin properly exercise the IsCompatible guard that returns false for invalid semver inputs.
  • resolveExactHardcodedPin tests correctly distinguish the SHA path (isAlreadySHA=true) from the version path (isAlreadySHA=false).

One non-blocking concern: misleading test case name

The "exact-version" case in TestFindCompatiblePin_SemverFallback (line 157–165) has a name that implies exact version matching, but findCompatiblePin performs major-compatible matching only. The test's custom availablePins (without v5.2.0) hides that requesting v5.0.0 when v5.2.0 is present would return v5.2.0, not v5.0.0. See inline comment for details. Non-blocking, but worth fixing to prevent reader confusion about the function's semantics.

Style ✅

  • Table-driven consolidation of TestGetContainerPin_MCPGatewayVersionsArePinned is a clean improvement.
  • assert.Zero usage is a good consistency improvement over assert.Equal(t, 0, ...).

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • proxy.golang.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "proxy.golang.org"

See Network Configuration for more information.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 96.5 AIC · ⌖ 6.96 AIC · ⊞ 4.9K

},
{
name: "exact-version",
version: "v5.0.0",

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.

The test case name "exact-version" is misleading: findCompatiblePin does not perform exact-version matching — it performs semver major-compatible matching (via semverutil.IsCompatible), returning the first pin whose major version matches the request.

The availablePins slice for this case was deliberately constructed without v5.2.0, so the result happens to be v5.0.0. But if the full pins slice (with v5.2.0 before v5.0.0) were used, findCompatiblePin(pins, "v5.0.0") would return v5.2.0, not v5.0.0, because that is the first major-compatible match.

This creates a false impression that the function honors exact version constraints. Consider:

  1. Renaming the case to something like "first-major-compatible-wins" or "major-compatible-match".
  2. Adding a sibling case that explicitly demonstrates that requesting v5.0.0 from a list containing v5.2.0 returns v5.2.0, clarifying the "first compatible, not exact" semantic.

@copilot please address this.

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.

Fixed in commit 9fd0ebe. The case was renamed from "exact-version" to "major-compatible-match" with a clarifying comment explaining that major-compatible matching is used (not exact-version), and that the only v5.x in that subtest's list happens to be v5.0.0. A sibling "first-compatible-not-exact" case was also added using the full pins slice to demonstrate that requesting v5.0.0 returns v5.2.0.

@github-actions github-actions 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.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 145.3 AIC · ⌖ 7.99 AIC · ⊞ 6.6K
Comment /matt to run again

name: "exact-major",
version: "v5",
wantFound: true,
wantVersion: "v5.2.0",

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.

[/tdd] The exact-major case implicitly depends on the pin list being sorted descending. findCompatiblePin returns the first compatible match, so if the list were [v5.0.0, v5.2.0], wantVersion would need to be "v5.0.0" — the hidden ordering assumption is unspecified in the test.

💡 Suggested improvement

Add a dedicated subtest that makes the first-match / pre-sorted semantics explicit:

{
    name:    "returns-first-compatible-not-highest",
    version: "v5",
    wantFound:   true,
    wantVersion: "v5.0.0", // first compatible, list unsorted
    availablePins: []ActionPin{
        {Version: "v5.0.0", SHA: "sha-low"},
        {Version: "v5.2.0", SHA: "sha-high"},
    },
},

resolveNonStrictHardcodedPin relies on callers supplying a pre-sorted slice (via GetActionPinsByRepo). Making this contract visible in the test prevents a future contributor from reversing the sort and getting subtly wrong pins.

@copilot please address this.

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.

Fixed in commit 9fd0ebe. Added "returns-first-compatible-not-highest" with an unsorted list [v5.0.0, v5.2.0], demonstrating that findCompatiblePin returns v5.0.0 (the first match) rather than v5.2.0. This makes the pre-sorted-slice contract explicit for callers.

stderrOutput := testutil.CaptureStderr(t, func() {
result = resolveNonStrictHardcodedPin("actions/checkout", "v5", pins, ctx)
})

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.

[/tdd] stderrOutput contains ANSI-styled text from console.FormatWarningMessage (the prefix plus applyStyle). An assert.Contains on a plain-string expectedWarning may pass in CI but fail in environments where the style rendering differs (e.g., no-color vs. colour-capable terminals).

💡 Suggested improvement

Strip ANSI codes before asserting, or match only the unambiguous message substring:

// Option A — assert on a known stable fragment
assert.Contains(t, stderrOutput, "using hardcoded pin for actions/checkout@v5.2.0")

// Option B — strip ANSI before comparing
import "github.com/acarl005/stripansi"
assert.Contains(t, stripansi.Strip(stderrOutput), expectedWarning)

Alternatively, testutil.CaptureStderr could normalise ANSI internally and document that guarantee.

@copilot please address this.

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.

Fixed in commit 9fd0ebe. All warning assertions now use the stable unstyled fragment "using hardcoded pin for actions/checkout@v5.2.0" instead of the full ANSI-decorated string, removing fragility across different terminal environments.


for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pin, found := findCompatiblePin(tt.availablePins, tt.version)

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.

[/tdd] The no-found branch asserts assert.Empty on both pin.Version and pin.SHA, but the returned ActionPin{} zero-value also has an empty Repo. Consider adding assert.Empty(t, pin.Repo) or a single assert.Equal(t, ActionPin{}, pin) to verify the full zero-value contract of the not-found return.

💡 Suggested fix
} else {
    assert.Equal(t, ActionPin{}, pin, "expected zero-value ActionPin when not found")
}

This is more robust than checking individual fields — if ActionPin gains new fields, the test still validates the whole zero-value.

@copilot please address this.

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.

Fixed in commit 9fd0ebe. Replaced assert.Empty(t, pin.Version) + assert.Empty(t, pin.SHA) with assert.Equal(t, ActionPin{}, pin, "expected zero-value ActionPin when not found"), which validates the full zero-value contract including any future fields.


result, ok := resolveExactHardcodedPin("actions/checkout", "v5.0.0", false, pins)

require.True(t, ok, "Expected exact version match to resolve")

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.

[/tdd] TestResolveExactHardcodedPin_ByVersion calls resolveExactHardcodedPin with isAlreadySHA=false but there is no test for the case where the requested version matches both a pin version and is technically a valid SHA string (i.e., isAlreadySHA=true + a matching version). The exact-version branch and the exact-SHA branch inside resolveExactHardcodedPin are separate code paths — the new tests cover only one.

💡 Suggested addition
func TestResolveExactHardcodedPin_VersionTakesPrecedenceOverSHA(t *testing.T) {
    // A version string that is also a syntactically valid SHA
    pins := []ActionPin{{Repo: "actions/checkout", Version: "sha-v5", SHA: "sha-v5"}}
    result, ok := resolveExactHardcodedPin("actions/checkout", "sha-v5", false, pins)
    require.True(t, ok)
    assert.Contains(t, result, "sha-v5")
}

This is a boundary the existing coverage silently skips.

@copilot please address this.

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.

Fixed in commit 9fd0ebe. Added TestResolveExactHardcodedPin_VersionTakesPrecedenceOverSHA using a pin where Version == SHA == "sha-v5" and isAlreadySHA=false. This shows the version-match loop runs and returns before the SHA loop is ever reached.

}

t.Run("uses semver-compatible pin when available", func(t *testing.T) {
ctx := &PinContext{Warnings: make(map[string]bool)}

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.

[/tdd] TestResolveNonStrictHardcodedPin_CompatibleAndFallback — the "uses semver-compatible pin" subtest calls resolveNonStrictHardcodedPin once and asserts that the warning is emitted. But it doesn't assert that a second call with the same version also deduplicates the warning (the dedup guard is at the resolveNonStrictHardcodedPin level, not just the fallback branch). That scenario is covered in the second subtest, but only for v9 (no-compatible path). The compatible path leaves a gap.

💡 Suggested addition
t.Run("deduplicates warning on compatible path", func(t *testing.T) {
    ctx := &PinContext{Warnings: make(map[string]bool)}
    stderrOutput := testutil.CaptureStderr(t, func() {
        resolveNonStrictHardcodedPin("actions/checkout", "v5", pins, ctx)
        resolveNonStrictHardcodedPin("actions/checkout", "v5", pins, ctx)
    })
    assert.Equal(t, 1, strings.Count(stderrOutput, "v5.2.0"),
        "Expected warning emitted exactly once for repeated compatible resolution")
    assert.Len(t, ctx.Warnings, 1)
})

@copilot please address this.

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.

Fixed in commit 9fd0ebe. Added a "deduplicates warning on compatible path" subtest in TestResolveNonStrictHardcodedPin_SelectsHighestCompatible that calls resolveNonStrictHardcodedPin twice with v5 and asserts the warning is emitted exactly once and ctx.Warnings has length 1.

}
}

func TestFindCompatiblePin_SemverFallback(t *testing.T) {

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.

[/tdd] TestFindCompatiblePin_SemverFallback has no subtest for a minor-version constraint (e.g. v5.1 requested, list has v5.2.0 and v5.0.0). If semverutil.IsCompatible handles minor pinning differently from major pinning, that logic is invisible from the current test matrix.

💡 Suggested case
{
    name:        "exact-minor",
    version:     "v5.1",
    wantFound:   true,
    wantVersion: "v5.2.0", // or v5.1.x if IsCompatible is minor-strict
    availablePins: []ActionPin{
        {Version: "v5.2.0", SHA: "sha-a"},
        {Version: "v5.0.0", SHA: "sha-b"},
    },
},

Even if v5.1 is currently not used in practice, documenting the expected behaviour in a test makes the semantics of IsCompatible explicit for this package.

@copilot please address this.

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.

Fixed in commit 9fd0ebe. Added "minor-version-constraint" case requesting v5.1 from [v5.2.0, v5.0.0], returning v5.2.0. This documents that IsCompatible performs major-only comparison, so minor constraints do not restrict the match.

assert.Empty(t, result, "Expected empty result when no exact match is found")
}

func TestResolveNonStrictHardcodedPin_CompatibleAndFallback(t *testing.T) {

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.

[/tdd] The test name TestResolveNonStrictHardcodedPin_CompatibleAndFallback bundles two distinct behaviours (compatible selection and no-compatible fallback) into one test function. Per /tdd, test names should read as specifications. Splitting into TestResolveNonStrictHardcodedPin_SelectsHighestCompatible and TestResolveNonStrictHardcodedPin_FallsBackToHighestWhenNoCompatible would make failures immediately diagnostic without reading subtests.

💡 Impact

When this test fails, the failing test name should tell you which behaviour broke. With bundled subtests under a single function, the failure shows TestResolveNonStrictHardcodedPin_CompatibleAndFallback/falls_back_to_highest... — which is reasonable but slightly noisier. The existing subtest names are good; the top-level function name is the gap.

This is a low-priority style note, not a blocking issue.

@copilot please address this.

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.

Fixed in commit 9fd0ebe. TestResolveNonStrictHardcodedPin_CompatibleAndFallback was split into two separate top-level test functions: TestResolveNonStrictHardcodedPin_SelectsHighestCompatible and TestResolveNonStrictHardcodedPin_FallsBackToHighestWhenNoCompatible. This is now outdated.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🤖 PR Triage — §28558548389

Field Value
Category test
Risk 🟢 Low
Score 44 / 100
Priority Medium
Recommended Action auto_merge
Batch batch-test-001

Score breakdown: Impact 18 · Urgency 10 · Quality 16

Rationale: Test-only PR adding internal coverage for pkg/actionpins edge cases (semver fallback, exact-match resolution, warning dedup). No behavior changes. Bot-approved review. Low blast radius — safe for auto-merge once CI confirms clean.

Generated by 🔧 PR Triage Agent · 52.1 AIC · ⌖ 8.26 AIC · ⊞ 1.6K ·

@pelikhan

pelikhan commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Copilot AI and others added 2 commits July 2, 2026 01:48
- Rename 'exact-version' → 'major-compatible-match' and add
  'first-compatible-not-exact' case clarifying first-match semantics (thread 1)
- Add 'returns-first-compatible-not-highest' case making list-ordering
  contract explicit (thread 2)
- Assert on stable unstyled fragment to remove ANSI fragility (thread 3)
- Replace assert.Empty×2 with assert.Equal(t, ActionPin{}, pin) in
  not-found branch (thread 4)
- Add TestResolveExactHardcodedPin_VersionTakesPrecedenceOverSHA (thread 5)
- Add 'deduplicates warning on compatible path' subtest (thread 6)
- Add 'minor-version-constraint' case for v5.1 major-only matching (thread 7)
- Split TestResolveNonStrictHardcodedPin_CompatibleAndFallback into
  TestResolveNonStrictHardcodedPin_SelectsHighestCompatible and
  TestResolveNonStrictHardcodedPin_FallsBackToHighestWhenNoCompatible (thread 8)

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

All 8 unresolved review threads have been addressed in the two new commits:

  • Thread 1 — Renamed "exact-version""major-compatible-match" (with a clarifying comment that the only v5.x present is v5.0.0, so the result only looks exact), and added "first-compatible-not-exact" demonstrating that requesting v5.0.0 from [v5.2.0, v5.0.0] returns v5.2.0.
  • Thread 2 — Added "returns-first-compatible-not-highest" case with an unsorted list [v5.0.0, v5.2.0] making the pre-sorted-slice contract explicit.
  • Thread 3 — Replaced full warning-string assertions with the stable unstyled fragment "using hardcoded pin for actions/checkout@v5.2.0" to remove ANSI-code fragility.
  • Thread 4 — Replaced assert.Empty(t, pin.Version) + assert.Empty(t, pin.SHA) with assert.Equal(t, ActionPin{}, pin) to verify the full zero-value contract.
  • Thread 5 — Added TestResolveExactHardcodedPin_VersionTakesPrecedenceOverSHA using a pin where Version == SHA to show the version-match loop runs before the SHA loop when isAlreadySHA=false.
  • Thread 6 — Added "deduplicates warning on compatible path" subtest verifying the dedup guard works on the compatible-selection path, not only the fallback path.
  • Thread 7 — Added "minor-version-constraint" case (v5.1 requested from [v5.2.0, v5.0.0]) documenting that IsCompatible uses major-only comparison.
  • Thread 8 — Split TestResolveNonStrictHardcodedPin_CompatibleAndFallback into TestResolveNonStrictHardcodedPin_SelectsHighestCompatible and TestResolveNonStrictHardcodedPin_FallsBackToHighestWhenNoCompatible.

make fmt, make lint, and make test-unit all pass locally.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address unresolved review comments, and rerun checks once the branch is up to date.

Generated by 👨‍🍳 PR Sous Chef · 8.66 AIC · ⌖ 21.3 AIC · ⊞ 6.4K ·

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, address unresolved review comments, and rerun checks once the branch is up to date.

...

All 8 unresolved review threads have been replied to (replies posted in this run). The code changes addressing each thread were already committed in 9fd0ebe and 5a8df35:

  • Thread 1 — Renamed "exact-version""major-compatible-match"; added "first-compatible-not-exact" case.
  • Thread 2 — Added "returns-first-compatible-not-highest" with unsorted pin list to make the pre-sorted-slice contract explicit.
  • Thread 3 — Replaced full ANSI-decorated warning strings with stable fragment "using hardcoded pin for actions/checkout@v5.2.0".
  • Thread 4 — Replaced individual assert.Empty calls with assert.Equal(t, ActionPin{}, pin, ...) for full zero-value validation.
  • Thread 5 — Added TestResolveExactHardcodedPin_VersionTakesPrecedenceOverSHA.
  • Thread 6 — Added "deduplicates warning on compatible path" subtest.
  • Thread 7 — Added "minor-version-constraint" case documenting major-only IsCompatible semantics.
  • Thread 8 — Split TestResolveNonStrictHardcodedPin_CompatibleAndFallback into two separate top-level test functions.

Local validation: make fmt ✅ · make lint ✅ · make test

Note: review threads could not be programmatically resolved (GraphQL API blocked in this environment) — a maintainer can resolve them manually or they will auto-resolve on merge.

Copilot AI requested a review from gh-aw-bot July 2, 2026 02:29
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address the unresolved review feedback, and rerun checks once the branch is ready for maintainer investigation. Unresolved review threads: github-actions[bot] #42834 (comment); github-actions[bot] #42834 (comment); github-actions[bot] #42834 (comment); github-actions[bot] #42834 (comment); github-actions[bot] #42834 (comment).

Generated by 👨‍🍳 PR Sous Chef · 26.9 AIC · ⌖ 10.6 AIC · ⊞ 6.4K ·

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, address the unresolved review feedback, and rerun checks once the branch is ready for maintainer investigation. Unresolved review threads: github-actions[b...

All 5 threads listed (and the remaining 3) already have code changes committed in 9fd0ebe/5a8df35 and individual replies posted. The threads remain technically open because GraphQL mutations are blocked in this environment — the threads cannot be resolved programmatically. A maintainer needs to resolve them manually (or they will auto-close on merge).

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🤖 PR Triage — Run §28572743533

Field Value
Category test
Risk 🟢 Low
Score 43 / 100
Breakdown Impact: 15 · Urgency: 10 · Quality: 18
Action auto_merge
Batch batch-test-001

✅ CI passing. Adds table-driven subtests for actionpins edge cases (+283/−25, 2 files + ADR). Low risk, well-scoped, ready to merge.

Generated by 🔧 PR Triage Agent · 64.3 AIC · ⌖ 9.84 AIC · ⊞ 1.6K ·

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, make sure the branch is up to date with main, address any remaining review feedback, and rerun checks.

Generated by 👨‍🍳 PR Sous Chef · 10.5 AIC · ⌖ 16.1 AIC · ⊞ 6.4K ·

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, make sure the branch is up to date with main, address any remaining review feedback, and rerun checks.

...

Branch is already up to date with main (last merged at d9fb5bd). All 8 review threads have code changes in 9fd0ebe/5a8df35 and individual replies posted. Local validation is clean: make fmt ✅ · make lint ✅ · make test ✅.

The only remaining step is that review threads cannot be resolved programmatically (GraphQL mutations are blocked in this environment). A maintainer needs to resolve them manually, then re-trigger CI.

@pelikhan pelikhan merged commit 6b0a2fe into main Jul 2, 2026
30 checks passed
@pelikhan pelikhan deleted the copilot/testify-expert-improve-test-quality branch July 2, 2026 11:58
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.82.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[testify-expert] Improve Test Quality: pkg/actionpins/actionpins_internal_test.go

4 participants