Skip to content

Strengthen actionpins spec tests for cache keys, fallback auditing, and container digest validation - #48497

Merged
pelikhan merged 2 commits into
mainfrom
copilot/testify-expert-improve-test-quality-one-more-time
Jul 28, 2026
Merged

Strengthen actionpins spec tests for cache keys, fallback auditing, and container digest validation#48497
pelikhan merged 2 commits into
mainfrom
copilot/testify-expert-improve-test-quality-one-more-time

Conversation

Copilot AI commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

This PR tightens pkg/actionpins/spec_test.go in the exact areas flagged by the test-quality issue: missing edge-case coverage, one weak assertion, and a missing malformed-digest scenario in container mapping behavior.

  • Cache key edge coverage

    • Extended TestSpec_PublicAPI_FormatCacheKey with explicit empty-input cases:
      • empty repo
      • empty version
      • both empty
  • Enforce-pinned assertion clarity

    • Added an explicit failure message to the assert.Equal checking ResolutionFailure.ErrorType in TestSpec_PublicAPI_ResolveActionPin_EnforcePinned.
  • Fallback auditing behavior for unknown repos

    • In TestSpec_PublicAPI_ResolveLatestActionPin_FallbackOnEnforceError (unknown-repo subtest), added a RecordResolutionFailure callback capture and assertion to validate callback behavior on the no-embedded-fallback path.
  • Container mapping malformed digest case

    • Added a subtest to TestSpec_PublicAPI_ApplyContainerPinMapping for mappings that include @sha256: but with a malformed digest, asserting mapping rejection and unchanged image output.
t.Run("invalid mapping - mapped value with malformed digest returns image unchanged", func(t *testing.T) {
	ctx := &actionpins.PinContext{
		Warnings: make(map[string]bool),
		ContainerMappings: map[string]string{
			"ghcr.io/owner/image:latest": "registry.acme.com/image:latest@sha256:not-a-valid-digest",
		},
	}
	result := actionpins.ApplyContainerPinMapping("ghcr.io/owner/image:latest", ctx)
	assert.Equal(t, "ghcr.io/owner/image:latest", result)
})

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve test quality for pkg/actionpins/spec_test.go Strengthen actionpins spec tests for cache keys, fallback auditing, and container digest validation Jul 28, 2026
Copilot AI requested a review from pelikhan July 28, 2026 03:31
@pelikhan
pelikhan marked this pull request as ready for review July 28, 2026 03:32
Copilot AI review requested due to automatic review settings July 28, 2026 03:32
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

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

No ADR enforcement needed: PR #48497 does not have the 'implementation' label and has ≤100 new lines of code in business logic directories (41 additions detected, threshold is 100).

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

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

Strengthens actionpins public API specification tests for edge cases and failure behavior.

Changes:

  • Adds empty cache-key input coverage.
  • Verifies unknown repositories do not emit resolution failures.
  • Tests malformed container digest rejection and improves assertion diagnostics.
Show a summary per file
File Description
pkg/actionpins/spec_test.go Expands edge-case and auditing assertions.

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: Medium

@pelikhan
pelikhan merged commit db0022d into main Jul 28, 2026
55 of 67 checks passed
@pelikhan
pelikhan deleted the copilot/testify-expert-improve-test-quality-one-more-time branch July 28, 2026 03:35
@github-actions github-actions Bot mentioned this pull request Jul 28, 2026

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

Skills-Based Review 🧠

Applied /tdd — the changes are a solid incremental improvement to spec coverage.

📋 Key Themes & Highlights

Positive Highlights

  • ✅ Empty-input cache key cases are a good boundary test — they pin the repo@version format contract explicitly
  • ✅ Adding an assertion message to the ErrorType check is a clear quality improvement
  • ✅ Capturing RecordResolutionFailure in the unknown-repo subtest correctly extends the observable spec
  • ✅ The malformed-digest container subtest meaningfully distinguishes from the "no digest" case

Minor Gaps (see inline comments)

  1. Malformed-digest subtest — missing assertion on ctx.Warnings absence to fully cover the rejection contract
  2. Unknown-repo subtest name — the callback-silence guarantee isn't reflected in the test name, making the spec harder to read

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 36.4 AIC · ⌖ 4.79 AIC · ⊞ 6.7K
Comment /matt to run again

}
result := actionpins.ApplyContainerPinMapping("ghcr.io/owner/image:latest", ctx)
assert.Equal(t, "ghcr.io/owner/image:latest", result,
"mapping with malformed @sha256 digest should be rejected and image returned unchanged")

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 new malformed-digest subtest doesn't assert the warning side-effect. The production code on line 577–580 of actionpins.go emits a warning to stderr but does NOT set ctx.Warnings, so the test is correct not to assert it — but it's worth verifying the non-presence of the mapping-applied warning key to prevent silent regressions.

💡 Suggested addition

Add a warning-key assertion after the assert.Equal to cover the full observable contract:

assert.False(t, ctx.Warnings["container-map:ghcr.io/owner/image:latest"],
    "invalid (malformed digest) mapping should not mark the mapping as applied")

This mirrors a similar assertion that would be valuable in the existing without-digest subtest too.

@copilot please address this.

},
}

result := actionpins.ResolveLatestActionPin("does-not-exist/x", 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] The new failures capture in the unknown-repo subtest asserts assert.Empty(t, failures), which is valuable. However, it also hides a subtle contract question: should an unknown repo with EnforcePinned: true not fire RecordResolutionFailure? If the intent is "empty result, no audit" that's fine, but the test name doesn't communicate this expectation. Consider renaming to make it explicit.

💡 Suggested rename
t.Run("unknown repo returns empty and does not audit a failure when no embedded fallback exists", func(t *testing.T) {

This makes the callback-silence guarantee part of the spec, not just an incidental assertion.

@copilot please address this.

@github-actions

Copy link
Copy Markdown
Contributor

Test Quality Sentinel Report

Test Quality Score: 96/100 — Excellent

Analyzed 4 new/modified test group(s): 4 design, 0 implementation, 0 violation(s).

Metrics (4 test groups, 17 sub-cases)
Metric Value
Analyzed 4 (Go: 4, JS: 0)
Design 4 (100%)
Implementation 0 (0%)
Edge/error coverage 4 (100%)
Duplicate clusters 0
Inflation No
Violations 0
Test File Classification Issues
TestSpec_PublicAPI_FormatCacheKey pkg/actionpins/spec_test.go behavioral_contract, high_value, design_test None
TestSpec_PublicAPI_ApplyContainerPinMapping pkg/actionpins/spec_test.go behavioral_contract, high_value, design_test None
TestSpec_PublicAPI_RecordResolutionFailure_WarningDedup pkg/actionpins/spec_test.go behavioral_contract, high_value, design_test None
TestSpec_PublicAPI_ResolveActionPin_EnforcePinned (modified) pkg/actionpins/spec_test.go behavioral_contract, high_value, design_test None

Verdict

passed. 0% implementation tests (threshold: 30%). All new tests verify user-visible behavioral contracts.

Highlights:

  • TestSpec_PublicAPI_FormatCacheKey: 5 table-driven rows covering standard format, semver, empty repo, empty version, and double-empty.
  • TestSpec_PublicAPI_ApplyContainerPinMapping: 5 cases including nil ctx, valid 64-hex digest, no-digest rejection, and malformed-digest rejection — enforces the container digest validation contract.
  • TestSpec_PublicAPI_RecordResolutionFailure_WarningDedup: validates that auditing is not deduplicated while warning emission is — a key design invariant.
  • TestSpec_PublicAPI_ResolveActionPin_EnforcePinned (modified): adds wantWarningKey assertion closing a coverage gap on warning-map side-effects.

References: https://github.com/github/gh-aw/actions/runs/30326214265

🧪 Test quality analysis by Test Quality Sentinel · sonnet46 · 51.1 AIC · ⌖ 8.04 AIC · ⊞ 8.1K ·
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: 96/100. 0% implementation tests (threshold: 30%). All 4 new/modified test groups are behavioral contracts with edge case coverage. No 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.

Test-only PR, low risk overall. One non-blocking observation posted inline about a duplicative subtest.

💡 Review notes
  • Empty-repo/empty-version cache-key cases are correct and trivially verify FormatCacheKey's simple concatenation.
  • The added assertion message on ErrorType and the RecordResolutionFailure callback assertion in the unknown-repo fallback subtest are solid, meaningful additions.
  • The new "malformed digest" container-mapping subtest, however, exercises the exact same regex-rejection branch as the pre-existing "without digest" subtest — see inline comment for a stronger alternative (e.g. wrong-length/case digest or wrong algorithm prefix) that would actually add coverage.

No correctness, concurrency, or security-adjacent issues found in this diff.

🔎 Code quality review by PR Code Quality Reviewer · sonnet50 · 47.2 AIC · ⌖ 4.41 AIC · ⊞ 7.4K
Comment /review to run again

"ghcr.io/owner/image:latest": "registry.acme.com/image:latest@sha256:not-a-valid-digest",
},
}
result := actionpins.ApplyContainerPinMapping("ghcr.io/owner/image:latest", 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.

This subtest largely duplicates the coverage of the adjacent "without digest" case rather than adding a distinct regression check.

💡 Details

containerDigestPinPattern is ^[a-zA-Z0-9][a-zA-Z0-9/:_.-]*@sha256:[a-f0-9]{64}$. Both "registry.acme.com/image:latest" (no digest at all) and "registry.acme.com/image:latest@sha256:not-a-valid-digest" fail the same [a-f0-9]{64} length/charset check and hit the identical MatchString false branch in ApplyContainerPinMapping. The two subtests exercise the same code path and produce the same behavior, so this addition does not actually close a coverage gap.

A more valuable malformed-digest case would target a distinct failure mode within the digest-present branch, e.g.:

// 64 hex chars but uppercase - fails [a-f0-9] charset only, digest length correct
"registry.acme.com/image:latest@sha256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
// correct length/charset but wrong algorithm name
"registry.acme.com/image:latest@sha512:"

Either would validate a different branch of the regex than the already-covered no-digest case.

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

The four additions are all correct and high-signal:

  • Cache key boundary cases: FormatCacheKey is repo+"@"+version, so @v4, actions/checkout@, and @ are the exact expected values.
  • Failure message on assert.Equal: Minor clarity improvement, no issues.
  • Fallback auditing assertion: ResolveLatestActionPin on an unknown repo bypasses RecordResolutionFailure entirely, so assert.Empty(failures) is accurate and adds real behavioral coverage.
  • Malformed digest container test: containerDigestPinPattern requires exactly 64 [a-f0-9] hex chars; not-a-valid-digest correctly fails, and the new subtest documents the rejection path complementing the existing no-digest case.

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 · sonnet46 · 25.6 AIC · ⌖ 4.57 AIC · ⊞ 5K

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.

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

3 participants