Skip to content

Add maintenance.disabled_jobs to selectively omit agentics-maintenance jobs and permissions#43300

Merged
pelikhan merged 12 commits into
mainfrom
copilot/issue-update-maintenance-workflow
Jul 4, 2026
Merged

Add maintenance.disabled_jobs to selectively omit agentics-maintenance jobs and permissions#43300
pelikhan merged 12 commits into
mainfrom
copilot/issue-update-maintenance-workflow

Conversation

Copilot AI commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

agentics-maintenance.yml was always generated with generic maintenance jobs, which could force unnecessary write scopes (notably PR/discussion permissions) even for issue-triage-only repos. This change adds repo-level control to omit specific maintenance jobs so generated permissions align with actual usage.

  • Config surface: selective maintenance job disablement

    • Added maintenance.disabled_jobs to .github/workflows/aw.json parsing and schema.
    • Supports job-name normalization (case-insensitive, _ and - treated equivalently).
  • Maintenance workflow generation

    • Omit configured jobs from generated agentics-maintenance.yml:
      • close-expired-entities
      • apply_safe_outputs
      • label_disable_agentic_workflow
      • label_apply_safe_outputs
    • Suppress issues:labeled trigger when all label-triggered jobs are disabled.
    • When apply_safe_outputs is disabled, workflow_call.outputs.applied_run_url now falls back to inputs.run_url (avoids output references to a removed job).
  • Docs and coverage

    • Updated ephemerals reference to document maintenance.disabled_jobs.
    • Added focused tests for config parsing and workflow omission behavior.
{
  "maintenance": {
    "runs_on": "ubuntu-latest",
    "disabled_jobs": [
      "close-expired-entities",
      "apply_safe_outputs",
      "label_apply_safe_outputs"
    ]
  }
}

Copilot AI and others added 2 commits July 4, 2026 04:37
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Update permissions in maintenance workflow for issue triage Add maintenance.disabled_jobs to selectively omit agentics-maintenance jobs and permissions Jul 4, 2026
Copilot AI requested a review from pelikhan July 4, 2026 04:42
@pelikhan

pelikhan commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

@copilot each job should have a minimal set of permissions write based on the required task

Copilot AI and others added 2 commits July 4, 2026 05:00
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot each job should have a minimal set of permissions write based on the required task

Updated in 7c84d1e: the expiry cleanup is now split into three jobs (close-expired-discussions, close-expired-issues, close-expired-pull-requests), each with only its required write permission, while keeping close-expired-entities as the disable switch for all three.

@pelikhan pelikhan marked this pull request as ready for review July 4, 2026 05:03
Copilot AI review requested due to automatic review settings July 4, 2026 05:03
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 4, 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

Adds a repo-level maintenance.disabled_jobs config surface to allow selectively omitting specific jobs (and related triggers/outputs) from the generated agentics-maintenance.yml, so the workflow’s permissions align with actual repo usage.

Changes:

  • Extend aw.json maintenance config + JSON schema to accept maintenance.disabled_jobs with job-name normalization (case-insensitive; _ and - equivalent).
  • Update maintenance workflow generation to omit disabled jobs, suppress the issues:labeled trigger when no label-triggered jobs remain, and avoid output references to removed jobs.
  • Add/adjust tests for config parsing and workflow omission behavior.
Show a summary per file
File Description
pkg/workflow/repo_config.go Adds MaintenanceConfig.DisabledJobs plus normalization + IsJobDisabled helper for config-driven job omission.
pkg/workflow/repo_config_test.go Adds parsing/normalization test coverage for maintenance.disabled_jobs.
pkg/workflow/maintenance_workflow.go Threads normalized disabled-job set into workflow YAML generation.
pkg/workflow/maintenance_workflow_yaml.go Implements job omission, conditional label trigger emission, and workflow_call output fallback when apply_safe_outputs is disabled.
pkg/workflow/maintenance_workflow_test.go Adds/updates tests verifying omitted jobs, permissions shaping, trigger suppression, and output fallback.
pkg/parser/schemas/repo_config_schema.json Updates schema to include maintenance.disabled_jobs.
docs/src/content/docs/reference/ephemerals.md Documents maintenance.disabled_jobs and provides example configuration.

Review details

Tip

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

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

Comment thread pkg/workflow/repo_config_test.go
Documents the decision to split close-expired-entities into three
scoped jobs and add maintenance.disabled_jobs config for selective
job omission.
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate - ADR Required

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

Draft ADR committed: docs/adr/43300-scoped-maintenance-job-permissions.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 documents two related decisions: (a) splitting close-expired-entities into three scoped jobs with minimal permissions, and (b) adding maintenance.disabled_jobs to aw.json for selective job omission
  2. Complete the missing sections - fill in the [TODO: verify] note on whether unknown job names should produce a validation error, and confirm the list of alternatives reflects what was actually 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-43300: Scoped Maintenance Job Permissions](docs/adr/43300-scoped-maintenance-job-permissions.md)

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.

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

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

⚠️ Test Quality Score: 70/100 — Acceptable

Analyzed 5 test(s): 4 design, 1 implementation, 0 violation(s).

📊 Metrics (5 tests)
Metric Value
Analyzed 5 (Go: 5, JS: 0)
✅ Design 4 (80%)
⚠️ Implementation 1 (20%)
Edge/error coverage 3 (60%)
Duplicate clusters 0
Inflation YES (maintenance_workflow_test.go: +119 test vs +9 prod)
🚨 Violations 0
Test File Classification Issues
TestGenerateMaintenanceWorkflow_DisabledJobs (new) maintenance_workflow_test.go design_test / high_value None
TestGenerateMaintenanceWorkflow_OperationJobConditions (modified) maintenance_workflow_test.go design_test / high_value None
TestGenerateMaintenanceWorkflow_PushTrigger (modified) maintenance_workflow_test.go design_test / high_value None
TestGenerateSideRepoMaintenanceWorkflow (modified) maintenance_workflow_test.go implementation_test / low_value Assertion change tracks refactor rename only
TestLoadRepoConfig_DisabledJobs (new) repo_config_test.go design_test / high_value None
⚠️ Flagged Tests (1)

TestGenerateSideRepoMaintenanceWorkflow (maintenance_workflow_test.go) — implementation_test, low_value. The changed assertion replaces the old close-expired-entities string check with three new job-name strings. This correctly tracks the renamed/split jobs, but only asserts absence via string matching — no positive assertion that the right jobs are present when expires is configured. Consider adding a positive assertion for the expected close-expired job names.

Inflation note: maintenance_workflow_test.go added 119 lines vs 9 lines in the production file (ratio ~13:1). This is expected here: the production logic is YAML generation and the test necessarily enumerates YAML content patterns. No remediation needed.

Verdict

Passed. 20% implementation tests (threshold: 30%). No guideline violations.

References:

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 · 49.9 AIC · ⌖ 14.2 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: 70/100. 20% implementation tests (threshold: 30%). 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.

Skills-Based Review 🧠

Applied /codebase-design, /tdd, /grill-with-docs, and /domain-modeling — requesting changes on a few design and test-coverage issues.

📋 Key Themes & Highlights

Key Themes

  • Dual implementation of the same logic: IsJobDisabled (exported, on MaintenanceConfig) and isMaintenanceJobDisabled (package-private, in the YAML builder) both call normalizeMaintenanceJobName and do the same lookup. One of them is unused in production paths and should either become the canonical API or be removed.
  • Virtual alias leaking into the public API: close-expired-entities is a grouping shorthand — it's not an actual YAML job ID. Users copying a job name from the generated workflow will not find it, leading to silent misconfiguration. The docs and schema need to enumerate recognized values.
  • Missing edge-case tests: partial label-job disablement (disable one, keep the other) and normalized-duplicate handling in disabled_jobs are not covered by the new tests.

Positive Highlights

  • ✅ Excellent refactor: the three close-expired jobs moved from one monolithic block to a writeCloseExpiredJob helper, each with its own minimal permission scope — a significant security improvement.
  • ✅ The issues:labeled trigger is now gated per surviving job rather than the coarser !disableLabelTrigger flag — correct and precise.
  • ✅ The applied_run_url fallback to inputs.run_url when apply_safe_outputs is omitted is a nice defensive touch that avoids a workflow-call failure.
  • ✅ Schema, struct, test, and docs are all updated together — well-rounded change.

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


// IsJobDisabled reports whether the provided maintenance job ID is explicitly
// disabled in aw.json.
func (m *MaintenanceConfig) IsJobDisabled(jobName 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.

[/codebase-design] IsJobDisabled is exported but not called from production code — the actual disable-check path uses the map[string]struct{} built in maintenance_workflow.go + isMaintenanceJobDisabled in maintenance_workflow_yaml.go. This leaves two parallel implementations of the same lookup logic.

💡 Consolidation options

Option A — make IsJobDisabled the single source of truth and remove the map-building loop + package-level isMaintenanceJobDisabled. The linear scan is fine for an expected list of ≤10 entries.

Option B — if the map is preferred for clarity or future performance, remove the unused IsJobDisabled method to avoid misleading future maintainers about the real code path.

Either way, normalizeMaintenanceJobName should live in exactly one place and both callers should use it.

@copilot please address this.

return *m.LabelTriggers
}

func normalizeMaintenanceJobName(name 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.

[/codebase-design] normalizeMaintenanceJobName lives in repo_config.go but is also called from maintenance_workflow.go and maintenance_workflow_yaml.go, making it an implicit cross-package coupling. It's an unexported helper that belongs to the module it serves.

💡 Suggested refactor

Move normalizeMaintenanceJobName next to isMaintenanceJobDisabled in maintenance_workflow_yaml.go (or a shared internal helper file), so that all normalization logic is co-located with its only real callsite. Alternatively, if IsJobDisabled is the canonical public API, keep normalizeMaintenanceJobName private inside repo_config.go and remove the inlined call in maintenance_workflow.go by delegating to IsJobDisabled.

@copilot please address this.

"type": "string",
"minLength": 1
},
"uniqueItems": true

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 schema has uniqueItems: true but there is no test asserting that a duplicate in disabled_jobs is rejected at parse time. If the JSON schema validator silently de-duplicates or if validation is not enforced at runtime, a user could write ["close-expired-entities", "close_expired_entities"] (one hyphen, one underscore) and get two semantically-identical but syntactically-unique entries that both pass schema validation while the normalisation in Go collapses them to one.

💡 Suggested test

Add a case to TestLoadRepoConfig_DisabledJobs (or a sibling) that checks both:

  1. A literal duplicate (same string twice) is rejected by the schema validator.
  2. A normalisation-equivalent pair like ["close-expired-entities", "close_expired_entities"] produces the expected set (one entry) without error — or alternatively is also rejected.

This makes the contract explicit regardless of which validator is in use.

@copilot please address this.

const { main } = require('${{ runner.temp }}/gh-aw/actions/close_expired_pull_requests.cjs');
await main();
`)
if !isMaintenanceJobDisabled(disabledJobs, "close-expired-entities") {

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.

[/grill-with-docs] The alias close-expired-entities is a virtual name — it does not correspond to any actual generated job. The generated jobs are close-expired-discussions, close-expired-issues, and close-expired-pull-requests. Using an alias that doesn't appear in the generated YAML is a leaky abstraction: users who copy a job name from the workflow output will get it wrong.

💡 Alternatives to consider
  1. Keep the alias, but document it clearly — add a comment block in the generated YAML (or in the docs) listing the valid job IDs, including the alias, so users know close-expired-entities is a shorthand.
  2. Remove the alias — accept only the concrete job names (close-expired-discussions, etc.) individually. Users then have fine-grained control and no confusion from an invisible name.
  3. Validate unknown job names — if a user passes a disabled_jobs value that doesn't match any recognized job, log a warning or return an error so misconfigurations surface immediately.

The current approach silently accepts unknown strings with no feedback to the user.

@copilot please address this.

t.Error("label_apply_safe_outputs job should be omitted when disabled in aw.json")
}
if strings.Contains(yaml, " issues:\n types: [labeled]") {
t.Error("issues:labeled trigger should be omitted when all label-triggered jobs are disabled")

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] TestGenerateMaintenanceWorkflow_DisabledJobs only tests the all-or-nothing case (all label-triggered jobs disabled). There is no test for the partial case: disabling just one of label_disable_agentic_workflow or label_apply_safe_outputs while keeping the other. In that scenario the issues:labeled trigger should still be emitted for the surviving job.

💡 Missing test case sketch

Disable only label_disable_agentic_workflow while LabelTriggers: true is set, then assert:

  • issues:labeled trigger is still present (surviving job needs it)
  • label_disable_agentic_workflow: job block is absent
  • label_apply_safe_outputs: job block is present

This covers the important edge: the trigger suppression logic in labelDisableJobEnabled || labelApplySafeOutputsJobEnabled needs a test to confirm it doesn't over-suppress.

@copilot please address this.

}

appliedRunURLValue := "${{ jobs.apply_safe_outputs.outputs.run_url }}"
if isMaintenanceJobDisabled(disabledJobs, "apply_safe_outputs") {

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] When apply_safe_outputs is disabled, applied_run_url falls back to ${{ inputs.run_url }}. The test at line 1194 checks this via a raw string comparison, but there is no test ensuring the generated YAML is actually valid and parsable as a GitHub Actions workflow. A malformed value: line would pass the strings.Contains check but break real workflow runs.

💡 Suggested hardening

After generating the YAML, try unmarshaling the workflow_call.outputs block with gopkg.in/yaml.v3 (or any YAML parser already used in the test suite) and assert that applied_run_url.value equals the expected expression string. This prevents a subtle formatting bug (e.g., missing newline before value:) from going undetected.

@copilot please address this.


// DisabledJobs lists maintenance job IDs that should be omitted from generated
// agentics-maintenance workflows.
DisabledJobs []string `json:"disabled_jobs,omitempty"`

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.

[/domain-modeling] The field is named DisabledJobs / disabled_jobs but the PR description uses both disabled_jobs and maintenance.disabled_jobs interchangeably, and the referenced values include both real YAML job IDs (apply_safe_outputs) and a virtual alias (close-expired-entities). The domain model mixes two concepts:

  • Concrete job identifiers — IDs that actually appear in the generated agentics-maintenance.yml
  • Virtual group aliases — shorthand names (close-expired-entities) that map to multiple concrete jobs

Without a clear distinction in the docs or schema description, users cannot know which names are valid without reading Go source.

💡 Suggestion

Add a JSON schema enum (or reference a $defs block) listing the recognized job IDs — both concrete and aliases — with a note in the description. This makes the contract self-documenting and enables IDE validation/autocompletion for aw.json.

@copilot please address this.

@@ -138,6 +143,8 @@ The `runs_on` field accepts a single string or an array of strings for multi-lab

The `action_failure_issue_expires` field controls expiration (in hours) for failure issues opened by the conclusion job (including grouped parent issues when `group-reports: true`). The default is `168` (7 days).

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.

[/grill-with-docs] The docs say job IDs are case-insensitive and _/- equivalent, but they don't list the valid job names a user can put in disabled_jobs. Without an exhaustive list (even a short one), users must read source code to know what strings are accepted — or silently misconfigure without any error feedback.

💡 Suggested addition

Add a table or list of recognized job IDs to the docs block, e.g.:

Job ID Effect when disabled
close-expired-entities Omits all three close-expired jobs
apply_safe_outputs Omits the apply-safe-outputs dispatch job; applied_run_url falls back to inputs.run_url
label_disable_agentic_workflow Omits the label-triggered disable job
label_apply_safe_outputs Omits the label-triggered apply-safe-outputs job

Also note what happens when an unrecognised job ID is provided (currently: silently ignored).

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

Review: maintenance.disabled_jobs selective job omission

Overall: The feature is well-designed and the refactoring from a monolithic close-expired-entities job to per-entity scoped-permission jobs is a clear win. Tests are comprehensive. Three non-trivial issues need attention before merging.

Blocking issues

  1. Duplicate normalization logic (repo_config.go L134): IsJobDisabled and the isMaintenanceJobDisabled helper in maintenance_workflow_yaml.go both implement the same normalization independently. A future change to normalization rules would need to be applied in both places.

  2. applied_run_url fallback scope (maintenance_workflow_yaml.go L113): The fallback to ${{ inputs.run_url }} is valid only during workflow_call; for schedule and workflow_dispatch it produces an empty string. Consumers of this output should be aware of this or it should be documented.

Non-blocking suggestions

  1. Schema and docs don't enumerate valid job IDs: The disabled_jobs array accepts any string with no validation. A typo silently does nothing. Adding enum values to the schema items and a table of valid IDs in the docs would significantly improve usability and discoverability.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 113 AIC · ⌖ 6.29 AIC · ⊞ 4.9K

normalizedJobName := normalizeMaintenanceJobName(jobName)
for _, disabledJob := range m.DisabledJobs {
if normalizeMaintenanceJobName(disabledJob) == normalizedJobName {
return true

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.

Duplicate normalization logicIsJobDisabled (added here) walks DisabledJobs with a linear scan, while maintenance_workflow.go builds a pre-normalised map[string]struct{} at generation time and calls the package-private isMaintenanceJobDisabled helper. The exported IsJobDisabled method is only used by tests, so there are now two parallel implementations of the same logic.

If IsJobDisabled is intended for external callers, the normalization rules are defined in two places. A change to the normalization logic must be applied in both normalizeMaintenanceJobName call-sites. Consider either removing IsJobDisabled if only tests use it (and add a helper that takes the map), or have IsJobDisabled convert to a map and reuse isMaintenanceJobDisabled.

@copilot please address this.

"type": "array",
"items": {
"type": "string",
"minLength": 1

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.

No enumeration of valid job IDs in schema — The disabled_jobs array accepts any string, but only a fixed set of job IDs are meaningful (close-expired-entities, apply_safe_outputs, label_disable_agentic_workflow, label_apply_safe_outputs). A typo like "apply-safe-outputs" (hyphen instead of underscore) silently has no effect even though normalization maps them equivalently — but "appl_safe_outputs" would be silently ignored with no warning.

Consider adding an enum or examples array to the item schema to help users discover valid values and improve IDE autocompletion.

@copilot please address this.

@@ -138,6 +143,8 @@ The `runs_on` field accepts a single string or an array of strings for multi-lab

The `action_failure_issue_expires` field controls expiration (in hours) for failure issues opened by the conclusion job (including grouped parent issues when `group-reports: true`). The default is `168` (7 days).

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.

Docs omit the full list of valid job IDs — The description says the field accepts job IDs and explains normalization, but never lists which IDs are actually recognised. Users need to know the valid values. The PR description lists them (close-expired-entities, apply_safe_outputs, label_disable_agentic_workflow, label_apply_safe_outputs), but that information isn't surfaced in the docs.

Please add a table or inline list of all supported job IDs with a brief description of what each one does so users can make an informed choice.

@copilot please address this.

appliedRunURLValue := "${{ jobs.apply_safe_outputs.outputs.run_url }}"
if isMaintenanceJobDisabled(disabledJobs, "apply_safe_outputs") {
appliedRunURLValue = "${{ inputs.run_url }}"
}

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.

Output fallback bypasses workflow_call consumer expectations — When apply_safe_outputs is disabled, applied_run_url is wired to ${{ inputs.run_url }}. But inputs.run_url is only available when the workflow is called via workflow_call — it is not populated for workflow_dispatch or schedule triggers, where it would resolve to an empty string.

Callers that consume the applied_run_url output expecting a valid URL may get an empty string silently. Consider either: (a) documenting this clearly, or (b) having the output emit the input only in the workflow_call path and omit/skip it otherwise.

@copilot please address this.

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category feature
Risk 🟡 Medium
Score 68 / 100
Action fast_track

Score breakdown: Impact 38 (new config surface reduces unnecessary write scopes in generated maintenance workflows) + Urgency 18 + Quality 12 (github-actions CHANGES_REQUESTED then DISMISSED, needs author follow-up)

Adds maintenance.disabled_jobs to selectively omit agentics-maintenance jobs and suppress unnecessary permissions. +461/-74 lines. One CHANGES_REQUESTED review was raised and then dismissed — review for design/test completeness before merging.

Generated by 🔧 PR Triage Agent · 82.8 AIC · ⌖ 8.09 AIC · ⊞ 5.5K ·

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill and address the unresolved review feedback before requesting final review. Remaining blocking themes from github-actions[bot]: (1) consolidate the duplicate disabled-job normalization logic so one canonical API is used, (2) document/schema the supported maintenance.disabled_jobs values including the close-expired-entities alias, and (3) add the missing edge-case tests for partial label-job disablement and normalized duplicate inputs. Rerun checks after updating.

Generated by 👨‍🍳 PR Sous Chef · 12.8 AIC · ⌖ 5.94 AIC · ⊞ 3.4K ·
Comment /souschef to run again

Copilot AI commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill and address the unresolved review feedback before requesting final review. Remaining blocking themes from github-actions[bot]: (1) consolidate the duplica...

Addressed on the current head in c90ca26 and 904e8d7: disabled-job checks now use the shared MaintenanceConfig.IsJobDisabled path, the schema/docs enumerate the supported maintenance.disabled_jobs values including close-expired-entities, and the tests cover normalized duplicates plus partial label-trigger disablement. I reran make fmt, make lint, make test-unit, make test, and make recompile locally; CI on 904e8d7 still needs a maintainer re-trigger because agent pushes do not start workflows.

Copilot AI requested a review from gh-aw-bot July 4, 2026 07:53
@pelikhan

pelikhan commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

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

Copilot AI commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix https://github.com/github/gh-aw/actions/runs/28698628049/job/85112795373

Fixed in d87438c: the gh CLI helper now builds cmd.Env from the configured process-env lookup instead of inheriting ambient runner tokens, which reproduces and fixes the impacted-go-tests failure. I reran go test ./pkg/workflow -run TestExecGHUsesConfiguredProcessEnvLookup, GH_TOKEN=ambient-token go test ./pkg/workflow -run TestExecGHUsesConfiguredProcessEnvLookup/does_not_inject_gh_token_when_both_tokens_are_absent, make test-impacted-go BASE_REF=origin/main, go test ./pkg/workflow, make fmt, and make agent-report-progress.

@pelikhan

pelikhan commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

@copilot merge main and fix conflicts

…maintenance-workflow

# Conflicts:
#	pkg/workflow/github_cli.go
#	pkg/workflow/github_cli_test.go

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

Copilot AI commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot merge main and fix conflicts

Done in 0c1296a: merged latest main, resolved the pkg/workflow/github_cli{,_test}.go conflicts, and reran make fmt, go test ./pkg/workflow -run 'TestExecGH|TestSetupGHCommandUsesDefaultGHHost', go test ./pkg/workflow, and make agent-report-progress.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, resolve the remaining blocking feedback, and rerun checks once the branch is ready. Remaining themes to address: (1) fix the current merge-main/conflict follow-up requested by the maintainer, (2) confirm the stale github-actions review feedback is fully addressed on the latest head, and (3) request/retrigger validation after the branch is updated.

Generated by 👨‍🍳 PR Sous Chef · 17 AIC · ⌖ 4.3 AIC · ⊞ 4.3K ·
Comment /souschef to run again

Copilot AI commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, resolve the remaining blocking feedback, and rerun checks once the branch is ready. Remaining themes to address: (1) fix the current merge-main/conflict fo...

Verified on 0c1296a: the merge-main/conflict follow-up is present, the stale github-actions feedback is already addressed on the latest head, and local validation passed (make fmt, make lint, make test-unit, make test, make recompile). No additional code changes were needed in this pass. CI on this head is still stale after the agent push, so a maintainer will need to re-trigger validation before merge.

@pelikhan pelikhan merged commit 586aeac into main Jul 4, 2026
30 checks passed
@pelikhan pelikhan deleted the copilot/issue-update-maintenance-workflow branch July 4, 2026 09:04
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.82.3

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.

Controlling required permissions in maintenance workflow

4 participants