Skip to content

Add dedicated unit coverage for activation step helpers - #49800

Merged
pelikhan merged 5 commits into
mainfrom
copilot/add-dedicated-unit-test-file
Aug 2, 2026
Merged

Add dedicated unit coverage for activation step helpers#49800
pelikhan merged 5 commits into
mainfrom
copilot/add-dedicated-unit-test-file

Conversation

Copilot AI commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

pkg/workflow/compiler_activation_steps.go had no dedicated unit test file despite containing a dense set of activation-job helpers, including several error-returning paths. This change adds focused coverage for those helpers so activation-step behavior is exercised directly instead of only through broader compiler tests.

  • New activation-step test file

    • Added pkg/workflow/compiler_activation_steps_test.go
    • Covers the helper surface called out in the issue, including reaction, OAuth token checks, cross-repo guidance, checkout/base-restore, lock-file checks, version checks, skill install steps, text output setup, status comments, safe-output message env wiring, issue locking, and default comment outputs
  • Direct success/error-path coverage

    • Adds explicit error-path assertions for helper methods that return error, especially around:
      • sanitization domain computation
      • activation repository/output orchestration
      • text-output setup
      • status-comment env/message wiring
    • Uses malformed model input to exercise the sanitization failure path directly
  • Focused assertions on generated activation YAML

    • Verifies emitted step names, ids, env wiring, script bindings, and output mappings without going through full workflow compilation for every case
    • Keeps the coverage local to the helper methods so regressions are easier to pinpoint

Example of the new direct helper-level coverage pattern:

ctx := newActivationBuildContext(&WorkflowData{
    NeedsTextOutput: true,
    Model:           "/bad-provider",
    EngineConfig:    &EngineConfig{ID: "opencode"},
}, false, "", "test.lock.yml")

err := compiler.addActivationRepositoryAndOutputSteps(ctx)
require.Error(t, err)

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.5 AIC · ⌖ 8.95 AIC · ⊞ 8.3K ·
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add dedicated unit test file for compiler_activation_steps.go Add dedicated unit coverage for activation step helpers Aug 2, 2026
Copilot AI requested a review from pelikhan August 2, 2026 15:02
@pelikhan
pelikhan marked this pull request as ready for review August 2, 2026 15:12
Copilot AI review requested due to automatic review settings August 2, 2026 15:12
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

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

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

Adds focused unit coverage for activation-job helper behavior and generated YAML.

Changes:

  • Tests activation step generation, skipping, outputs, and environment wiring.
  • Covers sanitization and orchestration failures.
  • Adds reusable activation test setup helpers.
Show a summary per file
File Description
pkg/workflow/compiler_activation_steps_test.go Adds activation helper unit tests.

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: 3
  • Review effort level: Balanced

err := addActivationSafeOutputMessagesEnv(ctx)

require.NoError(t, err)
assert.Contains(t, strings.Join(ctx.steps, ""), "GH_AW_SAFE_OUTPUT_MESSAGES:")
Comment on lines +445 to +447
err := addActivationSafeOutputMessagesEnv(ctx)

require.NoError(t, err)
Comment on lines +270 to +272
err := compiler.addActivationSkillInstallSteps(ctx)

require.NoError(t, err)

@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 new test file is well-structured and covers the target helper surface thoroughly — success paths, skip/no-op paths, and error paths are all exercised. Good use of t.Cleanup for the isReleaseBuild global and clear sub-test naming.

One minor note: some tests reach into the production newActivationBuildContext constructor while others use the local newActivationStepsTestContext helper. Both are valid, but a short comment explaining that newActivationStepsTestContext is a lightweight stand-in that bypasses full build-context initialisation would help future readers.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 20.5 AIC · ⌖ 10.3 AIC · ⊞ 5.4K

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 34/100 — Poor

Analyzed 45 test(s): 10 design, 35 implementation, 1 violation detected.

📊 Metrics (45 tests)
Metric Value
Analyzed 45 (Go: 45, JS: 0)
✅ Design 10 (22%)
⚠️ Implementation 35 (78%)
Edge/error coverage 15 (33%)
Duplicate clusters 2-3
Inflation ratio 1.36:1 (acceptable)
🚨 Violations 1 (implementation ratio exceeds 30%)
⚠️ Flagged Issues

Implementation Ratio Violation: 77.8% (threshold: 30%)

  • 35 of 45 tests verify step generation implementation details (string assertions on generated workflow YAML).
  • Only 10 tests verify behavioral contracts or error handling logic.

Duplicate Assertion Pattern

  • Pattern appears ~12 times with trivial constant changes.
  • Example: AddReactionStep, AddSecretValidationStep, AddOAuthTokenCheckStep follow identical structure.

String-Based Step Verification (Fragile)

  • Tests verify strings like 'Add eyes reaction', 'id: react', 'uses: actions/github-script'.
  • These are formatting details, not behavioral contracts.

Weak Output Assertions

  • Tests verify output map with string templates but don't verify downstream usage.

Verdict

Failed. 78% implementation tests (threshold: 30%). Tests mostly verify step generation implementation rather than behavioral contracts. Recommend refocusing on design-level invariants: error propagation, configuration resolution, state management, and conditional logic.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 19.7 AIC · ⌖ 5.4 AIC · ⊞ 8.5K ·
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: 34/100. 78% implementation tests (threshold: 30%). Tests mostly verify step generation implementation rather than behavioral contracts. Review flagged tests in the comment above.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate -- ADR Required

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

Draft ADR committed: docs/adr/49800-add-dedicated-unit-tests-for-activation-step-helpers.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-49800: Add Dedicated Unit Tests for Activation Step Helpers

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

Why ADRs Matter

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., 49800-add-dedicated-unit-tests-for-activation-step-helpers.md for PR #49800).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · sonnet46 · 71.6 AIC · ⌖ 19.3 AIC · ⊞ 9.6K ·
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.

Skills-Based Review 🧠

Applied /tdd and /codebase-design — requesting changes on a few structural issues before merge.

📋 Key Themes & Highlights

Key Themes

  • Test helper divergence: newActivationStepsTestContext bypasses newActivationBuildContext, so derived fields are set by hand. If the constructor changes, the tests won't catch it automatically. (Line 23)
  • Global variable mutation: isReleaseBuild is patched inline in two tests — this is a race hazard under -race. (Lines 142, 234)
  • Test names are descriptive, not specification-style: names like "adds reaction step" read as implementation notes rather than behavior contracts. (Pervasive)

Positive Highlights

  • ✅ Excellent helper-level coverage across 12+ helpers — this directly addresses the gap called out in the issue
  • ✅ Error-path assertions (require.Error) are present for all error-returning helpers
  • t.Cleanup is used correctly for global restore, which is an improvement over raw defer in table-driven tests
  • ✅ Clear separation: each Test* function targets exactly one helper method

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 41.5 AIC · ⌖ 8.43 AIC · ⊞ 7.1K
Comment /matt to run again

return compiler
}

func newActivationStepsTestContext(data *WorkflowData) *activationJobBuildContext {

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.

[/codebase-design] newActivationStepsTestContext duplicates logic from newActivationBuildContext — derived fields (hasReaction, reactionIssues, statusCommentIssues, etc.) are set by hand in individual tests instead of flowing through the real constructor. When the production constructor evolves, these tests can silently stop matching real behavior.

💡 Suggested fix

Replace the helper with a thin wrapper around the real constructor:

func newActivationStepsTestContext(data *WorkflowData) *activationJobBuildContext {
	if data == nil {
		data = &WorkflowData{}
	}
	return newActivationBuildContext(data, false, "", "test.lock.yml")
}

Then update call sites that manually set ctx.hasReaction = true to instead set data.AIReaction = "eyes", driving the field through the real code path and ensuring the test exercises the full initialization.

@copilot please address this.


func TestActivationStepsAddRepositoryAndOutputSteps(t *testing.T) {
t.Run("adds repository and output steps", func(t *testing.T) {
originalIsRelease := isReleaseBuild

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] isReleaseBuild is a package-level variable mutated directly in the test — this is a data race if tests ever run with -parallel or -race. The existing pattern in aw_info_versions_test.go uses defer for restore, but the race window still exists.

💡 Suggested fix

Instead of mutating the global, pass isRelease through the compiler constructor or accept it as a parameter to addActivationVersionCheckStep and addActivationRepositoryAndOutputSteps. This removes the shared-state dependency entirely and makes the tests safe to run in parallel:

t.Run("adds version check for release builds", func(t *testing.T) {
	t.Parallel()
	compiler := newActivationStepsTestCompiler("v1.2.3")
	compiler.isRelease = true // per-instance flag, not global
	...
})

If refactoring the compiler is too large for this PR, at minimum document the race risk with a //nolint:paralleltest comment and a TODO.

@copilot please address this.

compiler := newActivationStepsTestCompiler("")

t.Run("adds reaction step", func(t *testing.T) {
ctx := newActivationStepsTestContext(&WorkflowData{

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] Test names describe what the step does rather than the behavior being specified — e.g. "adds reaction step" vs "emits react step with configured emoji when reaction is enabled". With spec-style names, a failing test immediately tells you which contract broke.

💡 Example rename
// Before
t.Run("adds reaction step", ...)
t.Run("skips when reaction is disabled", ...)

// After
t.Run("emits react step wired to configured emoji when reaction is enabled", ...)
t.Run("emits no steps when reaction flag is not set", ...)

This is a low-effort, high-readability win — apply the pattern consistently across the file.

@copilot please address this.

compiler := newActivationStepsTestCompiler("")

t.Run("adds text output step", func(t *testing.T) {
ctx := newActivationStepsTestContext(&WorkflowData{

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] TestActivationStepsAddTextOutputStep tests the "adds text output step" sub-case but only checks that certain strings appear in the joined YAML — it does not assert the full env block is absent for the NeedsTextOutput: false case beyond checking ctx.steps is empty. Consider also asserting that no sanitized step ID leaks into a context that has unrelated steps accumulated prior to the call, i.e. testing isolation between calls.

💡 Missing edge case to add
t.Run("does not emit sanitized step when called after other steps", func(t *testing.T) {
	ctx := newActivationStepsTestContext(&WorkflowData{})
	ctx.steps = append(ctx.steps, "- name: prior-step\n")

	err := compiler.addActivationTextOutputStep(ctx)

	require.NoError(t, err)
	// Confirm the pre-existing step is unchanged and no sanitized step was added
	assert.Len(t, ctx.steps, 1)
	assert.NotContains(t, ctx.steps[0], "sanitized")
})

@copilot please address this.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the remaining review and check blockers on this PR, then run the pr-finisher skill.

Newest signals to close:

Please fix the failing unit-test signal first, then reconcile the remaining review feedback and ADR gate, and finish with a brief maintainer handoff.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.5 AIC · ⌖ 8.95 AIC · ⊞ 8.3K ·
Comment /souschef to run again

- Fix CI failure: update model from 'small' to 'claude-haiku-4.5' in
  pr-code-quality-reviewer.md (TestPRCodeQualityReviewerWorkflowSubAgentModelContract)
- Remove unreachable error return from addActivationSkillInstallSteps (always returned nil)
- Remove unreachable error return from addActivationSafeOutputMessagesEnv (json.Marshal
  cannot fail on SafeOutputMessagesConfig which contains only strings and bools)
- Update addActivationStatusCommentStep caller to not error-check removed return
- Update compiler_activation_job.go to call addActivationSkillInstallSteps without error check
- Strengthen test assertions: check serialized message value (not just key) in
  TestActivationStepsAddSafeOutputMessagesEnv and TestActivationStepsAddStatusCommentStep
- Update tests to match new non-error function signatures for skill install and messages env
- Complete ADR-49800: change status from Draft to Accepted, update consequences to reflect
  the unreachable error returns that were removed during focused test authoring

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI requested a review from gh-aw-bot August 2, 2026 16:18
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please continue triage on this PR.

Remaining reviewer-visible blockers:

  • Test Quality Sentinel still reports a blocking implementation-test ratio concern in the new activation helper coverage
  • Design Decision Gate requires the drafted ADR to be completed and linked from the PR body
  • once the tests are reshaped toward behavioral/design contracts, run the pr-finisher skill and leave a concise maintainer handoff

Run details: https://github.com/github/gh-aw/actions/runs/30757146330

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 13.8 AIC · ⌖ 6.26 AIC · ⊞ 5.9K ·
Comment /souschef to run again

@pelikhan
pelikhan merged commit 6056aca into main Aug 2, 2026
31 checks passed
@pelikhan
pelikhan deleted the copilot/add-dedicated-unit-test-file branch August 2, 2026 17:30
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.84.3

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.

[Code Quality] Add dedicated unit test file for compiler_activation_steps.go

4 participants