Skip to content

Fix activation job needs not populated from engine.env needs expressions - #49863

Merged
pelikhan merged 5 commits into
mainfrom
copilot/fix-activation-needs-jobs
Aug 3, 2026
Merged

Fix activation job needs not populated from engine.env needs expressions#49863
pelikhan merged 5 commits into
mainfrom
copilot/fix-activation-needs-jobs

Conversation

Copilot AI commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #30239: the activation job was not gaining needs entries for custom jobs referenced via needs.<job>.outputs.* in engine.env values (e.g. overriding COPILOT_GITHUB_TOKEN), even though the agent job already did. The activation step using the engine.env override would reference a job output before that job had run.

Changes

  • compiler_jobs.go — New getEngineEnvReferencedCustomJobsWithNoExplicitNeeds helper: scans engine.env values for needs.<job>.outputs.* patterns, returning only custom jobs with no explicit needs declaration (same filter logic as getCustomJobsReferencedInPromptWithNoActivationDep).

  • compiler_activation_outputs.goconfigureActivationNeedsAndCondition now calls the new helper, adding referenced engine.env jobs to customJobsBeforeActivation (the activation job's needs list).

  • compiler_custom_jobs.gogetCustomJobDependencySets now includes engine.env-referenced (no-explicit-needs) jobs in the pre-activation set, preventing activation from being auto-added to those jobs. Without this, the compiler would create a circular dependency: activation → custom_token → activation.

  • compiler_activation_outputs_test.go — Unit tests for the new behavior: no-explicit-needs jobs, case() expressions, with/without pre_activation, nil safety, deduplication, and cycle-safe exclusion of built-in job references.

Before / After

Given:

engine:
  env:
    COPILOT_GITHUB_TOKEN: ${{ case(needs.custom_token.outputs.use_custom == true, secrets.CUSTOM_TOKEN, secrets.COPILOT_GITHUB_TOKEN) }}
jobs:
  custom_token:
    runs-on: ubuntu-slim
    ...

Before:

jobs:
  activation:
    runs-on: ubuntu-slim          # missing needs: custom_token
  agent:
    needs: [activation, custom_token]

After:

jobs:
  activation:
    needs: [custom_token]         # ✓ correctly depends on custom_token
  agent:
    needs: [activation, custom_token]

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

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

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix activation job not incorporating needs entries from engine.env Fix activation job needs not populated from engine.env needs expressions Aug 2, 2026
Copilot AI requested a review from pelikhan August 2, 2026 22:43
@pelikhan
pelikhan marked this pull request as ready for review August 2, 2026 22:49
Copilot AI review requested due to automatic review settings August 2, 2026 22:49
@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

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

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Code Quality Reviewer failed during code quality 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

Fixes activation dependencies for custom-job outputs referenced by engine.env.

Changes:

  • Detects referenced custom jobs without explicit dependencies.
  • Wires them before activation while preventing dependency cycles.
  • Adds focused unit coverage.
Show a summary per file
File Description
pkg/workflow/compiler_jobs.go Adds engine environment reference detection.
pkg/workflow/compiler_custom_jobs.go Prevents circular activation dependencies.
pkg/workflow/compiler_activation_outputs.go Adds referenced jobs to activation needs.
pkg/workflow/compiler_activation_outputs_test.go Tests activation dependency behavior.

Review details

Tip

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

  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment on lines +75 to +76
for _, j := range c.getEngineEnvReferencedCustomJobsWithNoExplicitNeeds(data) {
promptReferencedJobs[j] = struct{}{}
Comment thread pkg/workflow/compiler_jobs.go Outdated
Comment on lines +189 to +191
for _, envValue := range data.EngineConfig.Env {
engineEnvBuilder.WriteByte('\n')
engineEnvBuilder.WriteString(envValue)

@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 fix is correct and well-structured. The new getEngineEnvReferencedCustomJobsWithNoExplicitNeeds function properly scans engine.env values for needs.<job>.outputs.* expressions and adds those custom jobs as activation prerequisites — mirroring the existing pattern for markdown-body-referenced jobs. Cycle prevention is handled correctly in both configureActivationNeedsAndCondition and getCustomJobDependencySets. Tests cover the key scenarios including nil safety, deduplication, and exclusion of built-in jobs.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 14 AIC · ⌖ 11.2 AIC · ⊞ 5.4K

@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 /diagnosing-bugs and /tdd — requesting changes on two small but concrete gaps.

📋 Key Themes & Highlights

Issues Found

  1. Missing cycle-guard regression test — the hasNeeds filter correctly prevents jobs with explicit needs (e.g. needs: activation) from being added to activation deps, but there's no test that pins this invariant. A future refactor could silently break it.

  2. Non-deterministic result orderinggetEngineEnvReferencedCustomJobsWithNoExplicitNeeds iterates over data.EngineConfig.Env (a map[string]string), which gives no ordering guarantee. getReferencedCustomJobs already sorts its output via sort.Strings; the new helper should do the same to keep compiled YAML deterministic.

Positive Highlights

  • ✅ Root cause is correctly diagnosed and fixed — activation was referencing job outputs before those jobs ran
  • ✅ The circular-dependency guard in getCustomJobDependencySets is a thoughtful companion change
  • ✅ Test coverage is comprehensive: nil safety, case() expressions, deduplication, built-in job exclusion
  • ✅ New helper mirrors the structure of the existing getCustomJobsReferencedInPromptWithNoActivationDep, keeping the codebase consistent

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

preActivationJob: false,
}

assert.NotPanics(t, func() {

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.

[/diagnosing-bugs] Missing regression test for the cycle-prevention invariant: a job with needs: activation referenced in engine.env must NOT be added to activation needs. The hasNeeds filter handles it correctly today, but without a test this can silently regress.

💡 Suggested test case
t.Run("engine.env reference to job with explicit needs is not added to activation needs", func(t *testing.T) {
    c := NewCompiler()
    data := &WorkflowData{
        EngineConfig: &EngineConfig{
            Env: map[string]string{
                "SOME_VAR": "${{ needs.post_job.outputs.token }}",
            },
        },
        Jobs: map[string]any{
            "post_job": map[string]any{
                "runs-on": "ubuntu-latest",
                "needs":   "activation",
            },
        },
    }
    ctx := &activationJobBuildContext{data: data}
    c.configureActivationNeedsAndCondition(ctx)
    assert.NotContains(t, ctx.activationNeeds, "post_job")
})

@copilot please address this.

referencedJobs := c.getReferencedCustomJobs(engineEnvBuilder.String(), data.Jobs)
var result []string
for _, jobName := range referencedJobs {
jobConfig, ok := data.Jobs[jobName].(map[string]any)

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.

[/diagnosing-bugs] The env-value iteration order is non-deterministic (Go map iteration). When two env values reference different custom jobs, the order they are appended to result (and therefore customJobsBeforeActivation) will vary across runs. This is benign today — slices.Contains deduplicates — but it can produce non-deterministic needs: ordering in the compiled YAML. Consider sorting result before returning, matching the pattern used by getCustomJobsReferencedInPromptWithNoActivationDep (line 172) and getReferencedCustomJobs (which already calls sort.Strings).

💡 One-line fix
// at end of getEngineEnvReferencedCustomJobsWithNoExplicitNeeds, before return:
sort.Strings(result)
return result

@copilot please address this.

…tion

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

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 81/100 — Excellent

Analyzed 7 test(s): 7 design, 0 implementation, 0 violation(s).

📊 Metrics (7 tests)
Metric Value
Analyzed 7 (Go: 7, JS: 0)
✅ Design 7 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 5 (71%)
Duplicate clusters 0
Inflation Yes (3.7:1)
🚨 Violations 0
Test File Classification Coverage
engine.env reference adds custom job to activation needs without pre_activation compiler_activation_outputs_test.go:15 design_test, high_value Happy path: engine.env → activation needs
engine.env reference with case() expression adds custom job to activation needs compiler_activation_outputs_test.go:42 design_test, high_value Complex expression: case(needs.X.outputs.Y == true, ...)
engine.env reference adds custom job to activation needs with pre_activation compiler_activation_outputs_test.go:70 design_test, high_value Pre-activation variant
engine.env with no needs references does not add extra deps compiler_activation_outputs_test.go:95 design_test, high_value Negative: non-referenced jobs excluded
engine.env reference to non-custom (built-in) job is not added to activation needs compiler_activation_outputs_test.go:120 design_test, high_value Boundary: built-in job filtering
nil engine.env does not panic compiler_activation_outputs_test.go:141 design_test, high_value Robustness: nil/missing config safety
job already in customJobsBeforeActivation is not duplicated compiler_activation_outputs_test.go:158 design_test, high_value Idempotency: deduplication guarantee
⚠️ Test Inflation Analysis

Ratio: 189 test lines / 51 production lines = 3.7:1 (exceeds 2:1 threshold)

Assessment: While high, inflation is justified:

  • New test file covers a critical dependency-graph compiler function
  • 7 comprehensive subtests with strong edge-case coverage (71%)
  • Prevents real CI/CD failures from activation job missing dependencies
  • All assertions are design-level, no trivial/duplicated checks
  • No false positives test (negative case), nil-safety, deduplication guard — essential for this domain

Verdict: Defensible for workflow compiler safety. Not a pattern issue.

Verdict

passed. 0% implementation tests (threshold: 30%). 100% design coverage with strong edge-case resilience. High inflation justified by domain criticality.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 23.7 AIC · ⌖ 6.78 AIC · ⊞ 8.5K ·
Comment /review to run again

@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 (252 new lines in pkg/workflow/) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/49863-extend-activation-needs-to-include-engine-env-job-references.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 at docs/adr/49863-extend-activation-needs-to-include-engine-env-job-references.md — it was generated from the PR diff
  2. Complete the missing sections — add context the AI could not infer, refine the decision rationale, and verify the listed alternatives match what you actually considered
  3. Commit the finalized ADR to docs/adr/ on your branch (the draft is already there)
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-49863: Extend Activation Job Dependency Resolution to Include engine.env Job References

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., 49863-extend-activation-needs-to-include-engine-env-job-references.md for PR #49863).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · sonnet46 · 41.6 AIC · ⌖ 32.5 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.

✅ Test Quality Sentinel: 81/100. 0% implementation tests (threshold: 30%). 100% design coverage with strong edge-case resilience.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

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

Outstanding review items:

  • github-actions: add the missing regression test that proves jobs with explicit needs are not re-added to activation dependencies.
  • github-actions: make the helper output deterministic by sorting the collected jobs before returning them.
  • Failed check to revisit: PR Code Quality Reviewer failed earlier: https://github.com/github/gh-aw/actions/runs/30770949091

Branch refresh may help once you are ready.

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

Copilot AI and others added 2 commits August 2, 2026 23:40
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

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

Outstanding review items:...

Implemented in 8643de7.

  • Added regression coverage that engine.env references do not re-add custom jobs with explicit needs to activation dependencies.
  • Made getEngineEnvReferencedCustomJobsWithNoExplicitNeeds deterministic by sorting returned jobs.
  • Scoped engine.env scanning to activation-rendered overrides only (required secret keys + COPILOT_GITHUB_TOKEN) so agent-only env keys no longer move custom jobs before activation.
  • Investigated failed PR Code Quality Reviewer run 30770949091: failure was No model available. Check policy enablement under GitHub Settings > Copilot in the agent runtime, not a compiler/test regression.

Copilot AI requested a review from gh-aw-bot August 2, 2026 23:48
@pelikhan
pelikhan merged commit 00142d6 into main Aug 3, 2026
29 checks passed
@pelikhan
pelikhan deleted the copilot/fix-activation-needs-jobs branch August 3, 2026 00:28
@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.

Activation 'needs' does not incorporate jobs in engine.env expressions

4 participants