feat: repo-level config via .github/workflows/aw.json#25227
feat: repo-level config via .github/workflows/aw.json#25227
Conversation
…ble support Agent-Logs-Url: https://github.com/github/gh-aw/sessions/e335a457-98e7-4995-9f16-5dc33e8cf528 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…lation Agent-Logs-Url: https://github.com/github/gh-aw/sessions/e335a457-98e7-4995-9f16-5dc33e8cf528 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
| const RepoConfigFileName = ".github/workflows/aw.json" | ||
|
|
||
| // MaintenanceConfig holds maintenance-workflow-specific settings from aw.json. | ||
| type MaintenanceConfig struct { |
There was a problem hiding this comment.
@copilot use json annotation and automatic deserilization
There was a problem hiding this comment.
Done in 01a7982. The manual map[string]any parsing has been replaced with:
RunsOnValue []string— implementsjson.Unmarshaler, accepting either a JSON string ("ubuntu-latest") or array (["self-hosted", "linux"]) and normalising to[]stringMaintenanceConfig— usesjson:"runs_on,omitempty"struct tag for automatic deserializationRepoConfig.UnmarshalJSON— handles the polymorphicmaintenancefield (booleanfalsevs object) usingjson.RawMessagethen standardjson.Unmarshal
The old parseRepoConfig and normaliseRunsOn helper functions have been removed.
… config Agent-Logs-Url: https://github.com/github/gh-aw/sessions/5655385a-f073-4c0b-bc78-3712627ebc18 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
Pull request overview
Adds optional repository-level configuration via .github/workflows/aw.json, enabling customization (or disabling) of the generated agentics-maintenance.yml workflow—primarily controlling the runs-on runner labels.
Changes:
- Introduces a repo config loader (
LoadRepoConfig) with JSON Schema validation and typed parsing (including polymorphicmaintenancehandling andruns_onas string-or-array). - Wires repo config into maintenance workflow generation to support custom
runs-onvalues and an explicitmaintenance: falseopt-out (deletes existing maintenance workflow and skips generation). - Adds schema embedding/compilation support and updates CLI compile/init paths to load and apply the config; expands tests accordingly.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/repo_config.go | Implements loading/validation/parsing of .github/workflows/aw.json, plus runs_on formatting helper. |
| pkg/workflow/repo_config_test.go | Adds unit tests for repo config loading, schema enforcement, and runs-on formatting. |
| pkg/workflow/maintenance_workflow.go | Applies repo config to maintenance workflow generation (custom runner / disable behavior). |
| pkg/workflow/maintenance_workflow_test.go | Updates existing tests for new function signature and adds repo-config-specific coverage. |
| pkg/parser/schemas/repo_config_schema.json | Defines JSON Schema for aw.json with strict properties and polymorphic maintenance. |
| pkg/parser/schema_compiler.go | Embeds and caches compiled repo config schema. |
| pkg/cli/init.go | Loads repo config during init and passes it into maintenance workflow generation. |
| pkg/cli/compile_post_processing.go | Loads repo config during compile post-processing (strict/non-strict behavior) and passes it through. |
| pkg/cli/compile_pipeline.go | Updates post-processing call to provide gitRoot for config loading. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 9/9 changed files
- Comments generated: 2
| func FormatRunsOn(runsOn RunsOnValue, defaultRunsOn string) string { | ||
| if len(runsOn) == 0 { | ||
| return defaultRunsOn | ||
| } | ||
| if len(runsOn) == 1 { | ||
| if runsOn[0] == "" { | ||
| return defaultRunsOn | ||
| } | ||
| return runsOn[0] | ||
| } | ||
| // Multiple labels → inline YAML sequence notation: ["a", "b", "c"] | ||
| var sb strings.Builder | ||
| sb.WriteString("[") | ||
| for i, s := range runsOn { | ||
| if i > 0 { | ||
| sb.WriteString(", ") | ||
| } | ||
| sb.WriteString(`"`) | ||
| sb.WriteString(s) | ||
| sb.WriteString(`"`) | ||
| } | ||
| sb.WriteString("]") | ||
| return sb.String() |
There was a problem hiding this comment.
FormatRunsOn builds an inline YAML value via string concatenation without escaping. Because runner labels come from aw.json and the schema currently allows arbitrary strings, a value containing quotes, backslashes, or newlines can produce invalid YAML (and in the worst case allow YAML injection into the generated workflow). Consider generating the scalar/sequence using a proper encoder (e.g., json.Marshal for a YAML-compatible JSON inline scalar/array) and/or tightening the schema with a safe pattern that disallows control characters/newlines.
| // Respect explicit opt-out from aw.json: maintenance: false | ||
| if repoConfig != nil && repoConfig.MaintenanceDisabled { | ||
| maintenanceLog.Print("Maintenance disabled via repo config, skipping generation") | ||
| maintenanceFile := filepath.Join(workflowDir, "agentics-maintenance.yml") | ||
| if _, err := os.Stat(maintenanceFile); err == nil { | ||
| maintenanceLog.Printf("Deleting existing maintenance workflow: %s", maintenanceFile) | ||
| if err := os.Remove(maintenanceFile); err != nil { | ||
| return fmt.Errorf("failed to delete maintenance workflow: %w", err) | ||
| } | ||
| } | ||
| return nil | ||
| } |
There was a problem hiding this comment.
When repoConfig.MaintenanceDisabled is true, the function returns early even if workflows contain expires configs. That means expires will silently stop working (no maintenance workflow will run) which conflicts with the PR description’s claim that dependent features are “suppressed/refused”. Either update the behavior to emit an error/warning (especially in strict mode) when expires is present while maintenance is disabled, or adjust the description/docs to reflect that expires becomes a no-op.
Adds an optional
.github/workflows/aw.jsonfile for repository-level agentic workflow settings, starting with control over theagentics-maintenance.ymlrunner.Schema & Loading
pkg/parser/schemas/repo_config_schema.json(embedded, validated on load)pkg/workflow/repo_config.go— loads, validates against schema, and parses into typed structsSupported Configuration
Custom runner (string or array):
{ "maintenance": { "runs_on": "my-custom-runner" } }{ "maintenance": { "runs_on": ["self-hosted", "linux"] } }Disable maintenance entirely (also suppresses features that depend on it, e.g.
expires):{ "maintenance": false }Wiring
runs-on: ubuntu-sliminmaintenance_workflow.goreplaced with the configured value (defaulting toubuntu-slim)GenerateMaintenanceWorkflowaccepts a new*RepoConfigparameter;nilpreserves existing behaviourcompile_post_processing.goandinit.gobefore maintenance workflow generationmaintenance: falsedeletes any existingagentics-maintenance.ymland skips generation