Skip to content

Enforce explicit job and step timeouts on Visual Regression Checker workflow - #56980

Merged
pelikhan merged 6 commits into
mainfrom
copilot/deep-report-add-timeout-to-checker
Aug 29, 2026
Merged

Enforce explicit job and step timeouts on Visual Regression Checker workflow#56980
pelikhan merged 6 commits into
mainfrom
copilot/deep-report-add-timeout-to-checker

Conversation

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

The Visual Regression Checker workflow lacked explicit job and setup step timeouts, causing hanging runs to occupy CI runners for 1.6–2.0 hours before failing. Top-level timeout-minutes only bounded the agentic_execution step, leaving the agent job (default 60m), safe_outputs job (default 45m), and pre-execution setup steps unconstrained.

Workflow Timeouts

  • Job Timeouts: Configured jobs.agent.timeout-minutes: 15 and safe-outputs.timeout-minutes: 10 in .github/workflows/visual-regression-checker.md.
  • Step Timeouts: Added timeout-minutes to setup steps (npm ci: 5m, npm run build: 5m, Wait for server readiness: 2m).
  • Lockfile Sync: Recompiled .github/workflows/visual-regression-checker.lock.yml.

Compiler Step Timeout Parsing

  • Updated MapToStep in pkg/workflow/step_types.go to handle uint64, int64, float64, and numeric string types for step-level timeout-minutes (emitted during YAML unmarshaling) with math.MaxInt bounds checks.
jobs:
  agent:
    timeout-minutes: 15
safe-outputs:
  timeout-minutes: 10
timeout-minutes: 15

steps:
  - name: Install dependencies
    working-directory: ./docs
    timeout-minutes: 5
    run: npm ci

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

Warning

Firewall blocked 1 domain

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

  • github.com

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

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 41.6 AIC · ⌖ 8.71 AIC · ⊞ 9.2K ·
Comment /souschef to run again

Copilot AI and others added 2 commits August 29, 2026 22:03
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…low and add bounds check for step timeout-minutes

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add timeout to Visual Regression Checker workflow Enforce explicit job and step timeouts on Visual Regression Checker workflow Aug 29, 2026
Copilot AI requested a review from pelikhan August 29, 2026 22:13
@pelikhan
pelikhan marked this pull request as ready for review August 29, 2026 22:25
Copilot AI balanced review requested due to automatic review settings August 29, 2026 22:25
@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

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

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Ponytail Reviewer. Review the logs for details.

Warning

Firewall blocked 4 domains

The following domains were blocked by the firewall during workflow execution:

  • ab.chatgpt.com
  • api.github.com
  • chatgpt.com
  • github.com

[!TIP]
api.github.com is blocked because GitHub API access uses the built-in GitHub tools by default. Instead of adding api.github.com to network.allowed, use tools.github.mode: gh-proxy for direct pre-authenticated GitHub CLI access without requiring network access to api.github.com:

tools:
  github:
    mode: gh-proxy

See GitHub Tools for more information on gh-proxy mode.

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

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"
    - "api.github.com"
    - "chatgpt.com"
    - "github.com"

See Network Configuration for more information.

Generated by Ponytail Reviewer for #56980

@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

Completed PR review for #56980 using local diff/comments; actionable findings will be surfaced in the final review if any exist.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-08-29T00:00:00Z
review_event: COMMENT
top_themes:
  - no blocking issues found in changed lines
  - timeout parsing behavior still loosely validated but not regressed by this patch
files_reviewed:
  - .github/workflows/visual-regression-checker.md
  - .github/workflows/visual-regression-checker.lock.yml
  - pkg/workflow/step_types.go
  - pkg/workflow/step_types_test.go
comment_count: 0

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · pi · gpt54 · 19.3 AIC · ⌖ 7.28 AIC · ⊞ 7.2K ·
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.

Verdict

Non-blocking from the changed lines I reviewed.

Details

I checked the workflow timeout additions and the new timeout-minutes parsing path. The workflow changes do what the PR claims, and I did not find a changed-line bug that clearly warrants blocking merge.

One caveat: parseStepTimeoutMinutes now accepts more input shapes than the documented frontmatter contract elsewhere in the repo, but that inconsistency predates this review surface and is not a changed-line break by itself.

🔎 Code quality review by PR Code Quality Reviewer · pi · gpt54 · 19.3 AIC · ⌖ 7.28 AIC · ⊞ 7.2K
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.

The PR is mostly lean; the only clear cut is collapsing the one-caller parsing helpers back into MapToStep to avoid indirection. net: -20 lines possible.

Warning

Firewall blocked 4 domains

The following domains were blocked by the firewall during workflow execution:

  • ab.chatgpt.com
  • api.github.com
  • chatgpt.com
  • github.com

[!TIP]
api.github.com is blocked because GitHub API access uses the built-in GitHub tools by default. Instead of adding api.github.com to network.allowed, use tools.github.mode: gh-proxy for direct pre-authenticated GitHub CLI access without requiring network access to api.github.com:

tools:
  github:
    mode: gh-proxy

See GitHub Tools for more information on gh-proxy mode.

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

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"
    - "api.github.com"
    - "chatgpt.com"
    - "github.com"

See Network Configuration for more information.

Generated by ✂️ Ponytail Reviewer for #56980 · codex · mai10 · 4.28 AIC · ⌖ 0.441 AIC · ⊞ 14K
Comment /ponytail to run again

return step, nil
}

func parseStepEnv(env map[string]any) map[string]string {

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.

pkg/workflow/step_types.go:140: yagni: three one-caller parsing helpers for env/continue-on-error/timeout. Inline the small switch logic in MapToStep and keep the mapping local.

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

Good PR — the timeout enforcement is well-scoped and the parseStepTimeoutMinutes refactor correctly handles multiple numeric types with appropriate bounds checks. Two non-blocking consistency issues were flagged:

  1. int case missing > 0 guard — the int64, uint64, and float64 branches all reject non-positive values, but the int case does not.
  2. string case accepts negative stringsstrconv.Atoi("-5") succeeds, so a negative string timeout would pass through silently.

Neither is blocking for this PR's primary goal, but both should be addressed for correctness.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet46 · 27.3 AIC · ⌖ 10.7 AIC · ⊞ 6.2K

case int:
return v
case int64:
if v > 0 && v <= int64(math.MaxInt) {

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 int case does not guard against zero or negative values, unlike the int64, uint64, and float64 branches which all check v > 0. A zero or negative timeout would be silently accepted and may behave unexpectedly.

Suggested fix:

case int:
    if v > 0 {
        return v
    }

@copilot please address this.

case float64:
if v > 0 && v <= float64(math.MaxInt) {
return int(v)
}

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 string case parses via strconv.Atoi but does not reject negative values like "-5". strconv.Atoi("-5") returns -5, nil so a negative string timeout would be silently accepted.

Suggested fix:

case string:
    if n, err := strconv.Atoi(v); err == nil && n > 0 {
        return n
    }

@copilot please address this.

@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 two correctness issues in parseStepTimeoutMinutes and its test coverage.

📋 Key Themes & Highlights

Issues Found

  • Missing lower-bound guard (step_types.go): The int and string branches of parseStepTimeoutMinutes don't reject negative values, while the int64 and float64 branches do. A timeout-minutes: -5 in a workflow silently produces a negative int.
  • Test coverage gap (step_types_test.go): The new table test only covers valid positive inputs. There are no cases for negative values, zero, or unsupported types, which means the inconsistent guard logic wasn't caught by the tests.
  • safe-outputs timeout headroom (.lock.yml): Reducing from 45m → 10m is sensible to stop runaway jobs, but 10m may be tight if many write intents are queued post-agent. Consider 15–20m.

Positive Highlights

  • ✅ Extracting parseStepEnv, parseStepContinueOnError, and parseStepTimeoutMinutes as standalone helpers is a clean design improvement — easier to test, easier to read.
  • ✅ The math.MaxInt bounds check on uint64 and int64 correctly prevents integer overflow.
  • ✅ Step-level timeouts on npm ci, npm run build, and the server-readiness wait are well-chosen values that match realistic worst-case durations.
  • ✅ Tests are structured cleanly with table-driven subtests and clear names.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet46 · 20 AIC · ⌖ 10.8 AIC · ⊞ 7.6K
Comment /matt to run again

return &templatableValue
}
}
return nil

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 int case in parseStepTimeoutMinutes lacks the > 0 lower-bound guard present in the int64 and float64 branches, so a negative value like timeout-minutes: -5 passes through silently.

💡 Suggested fix + missing test
case int:
    if v > 0 {
        return v
    }

The string branch via strconv.Atoi has the same gap — a "-5" string returns a negative int. Both should return 0 (treated as absent) or produce a validation error.

A regression test covering invalid inputs (negative ints, negative strings, zero) would prevent this from regressing.

@copilot please address this.

}
step, err := MapToStep(stepMap)
require.NoError(t, err)
assert.Equal(t, tt.want, step.TimeoutMinutes)

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 test TestMapToStep_TimeoutMinutesNumericTypes only covers happy-path values; there are no cases for invalid inputs (negative numbers, zero, unsupported types like bool). The gaps in the guard logic above mean these aren't caught.

💡 Suggested additional test cases
{"negative int",    -1,       0},
{"zero",            0,        0},
{"negative float",  float64(-3), 0},
{"negative string", "-5",     0},
{"bool (unsupported)", true,  0},

Having these in the table would have caught the missing lower-bound guard before the PR was submitted.

@copilot please address this.

issues: write
pull-requests: write
timeout-minutes: 45
timeout-minutes: 10

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] The safe-outputs job timeout was reduced from 45m → 10m. The safe-outputs job is responsible for all GitHub write operations after the agent completes. If a complex run produces many write intents, 10m may be too tight, causing the job to time out before all writes are committed.

💡 Consider a slightly larger buffer

The agent job is capped at 15m, which is reasonable. But safe-outputs processes the agent's outputs after it finishes, and depending on how many write operations are queued, it may need more than 10m on a slow runner. A value of 15m (matching the agent job) or 20m would provide safer headroom without re-introducing the original 45m problem.

@copilot please address this.

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.

🟡 Changes recommended

Float timeout parsing can truncate fractional values and permit an out-of-range conversion.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds explicit runtime bounds to prevent prolonged Visual Regression Checker runs.

Changes:

  • Adds agent, safe-output, and setup-step timeouts.
  • Expands step-timeout parsing and tests.
  • Regenerates the compiled workflow.
File summaries
File Description
.github/workflows/visual-regression-checker.md Configures explicit timeouts.
.github/workflows/visual-regression-checker.lock.yml Updates generated workflow.
pkg/workflow/step_types.go Parses additional timeout numeric types.
pkg/workflow/step_types_test.go Tests supported timeout representations.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +178 to +181
case float64:
if v > 0 && v <= float64(math.MaxInt) {
return int(v)
}
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the latest review feedback on this PR, then run the pr-finisher skill.

Priority items from the current reviews:

  • reject negative and zero-invalid timeout-minutes values consistently across int, int64, uint64, float64, and string inputs
  • tighten float parsing so fractional or out-of-range timeout values cannot truncate into invalid integers
  • extend tests to cover negative, zero, string, and unsupported timeout inputs

Failed checks to fix:

Please also refresh the branch if needed while addressing the review comments.

Warning

Firewall blocked 1 domain

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

  • github.com

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

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 41.6 AIC · ⌖ 8.71 AIC · ⊞ 9.2K ·
Comment /souschef to run again

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@gh-aw-bot Unfortunately I hit an unexpected error while processing your comment. I've automatically reported this to GitHub.

You can ask me to try again later by mentioning me in a new comment.

If you want to contact GitHub about this error, please mention the following identifier so they can better serve you: d576d887-7cb4-4681-a1c2-2f2158e51139

Sorry for the inconvenience!

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please address the latest review feedback on this PR, then run the pr-finisher skill.

Priority items from the current reviews:...

Addressed in 3d6ea7a:

  • parseStepTimeoutMinutes now rejects non-positive values consistently for int, int64, uint64, float64, and string inputs.
  • Float handling rejects NaN/Inf, fractional values (so 1.9 is no longer truncated to 1), and values at/above the float64(math.MaxInt) boundary, matching the bounded-int handling used for job timeouts.
  • Test table extended with negative, zero, fractional, out-of-range, non-numeric string, bool, and nil cases.

On the failing Unit tests (N-R) check: the failure is TestPRCodeQualityReviewerWorkflowSubAgentModelContract, which is unrelated to this PR. .github/workflows/pr-code-quality-reviewer.md was switched to model: openai/gpt-5.4 in #56965 while the contract test still asserts model: copilot/gpt-5.4; both files are unchanged on this branch and the test fails on main at 62e07e6 as well. It needs a separate fix.

@pelikhan

Copy link
Copy Markdown
Collaborator

…ontract test

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

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix https://github.com/github/gh-aw/actions/runs/33279871262/job/99174322748?pr=56980

Fixed in d8b2a1a.

The failing job was TestPRCodeQualityReviewerWorkflowSubAgentModelContract. #56965 moved .github/workflows/pr-code-quality-reviewer.md to the Pi engine with model-provider: openai / model: openai/gpt-5.4, but the contract test still hardcoded model: copilot/gpt-5.4.

The test now asserts a top-level provider-qualified model via regexp ^model: \S+/\S+$, preserving the original intent (an explicit, non-inherited main-agent model) while staying provider-agnostic. model: inherited still fails the assertion since it has no provider prefix. The other three assertions are unchanged.

Test passes locally, and make agent-report-progress is green (297/297 workflows compiled, lock files in sync).

@pelikhan
pelikhan merged commit aa70602 into main Aug 29, 2026
@pelikhan
pelikhan deleted the copilot/deep-report-add-timeout-to-checker branch August 29, 2026 23:44
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.87.10

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.

[deep-report] Visual Regression Checker lacks a timeout: 2 of last 3 runs hung 1.6-2.0 hours before failing

4 participants