Skip to content

feat: repo-level config via .github/workflows/aw.json#25227

Open
Copilot wants to merge 4 commits intomainfrom
copilot/add-support-for-aw-json-config
Open

feat: repo-level config via .github/workflows/aw.json#25227
Copilot wants to merge 4 commits intomainfrom
copilot/add-support-for-aw-json-config

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

Adds an optional .github/workflows/aw.json file for repository-level agentic workflow settings, starting with control over the agentics-maintenance.yml runner.

Schema & Loading

  • New JSON schema at pkg/parser/schemas/repo_config_schema.json (embedded, validated on load)
  • pkg/workflow/repo_config.go — loads, validates against schema, and parses into typed structs
  • File is optional; absence returns safe defaults

Supported 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

  • All hardcoded runs-on: ubuntu-slim in maintenance_workflow.go replaced with the configured value (defaulting to ubuntu-slim)
  • GenerateMaintenanceWorkflow accepts a new *RepoConfig parameter; nil preserves existing behaviour
  • Config loaded in compile_post_processing.go and init.go before maintenance workflow generation
  • maintenance: false deletes any existing agentics-maintenance.yml and skips generation

Copilot AI and others added 2 commits April 8, 2026 00:48
const RepoConfigFileName = ".github/workflows/aw.json"

// MaintenanceConfig holds maintenance-workflow-specific settings from aw.json.
type MaintenanceConfig struct {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use json annotation and automatic deserilization

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 01a7982. The manual map[string]any parsing has been replaced with:

  • RunsOnValue []string — implements json.Unmarshaler, accepting either a JSON string ("ubuntu-latest") or array (["self-hosted", "linux"]) and normalising to []string
  • MaintenanceConfig — uses json:"runs_on,omitempty" struct tag for automatic deserialization
  • RepoConfig.UnmarshalJSON — handles the polymorphic maintenance field (boolean false vs object) using json.RawMessage then standard json.Unmarshal

The old parseRepoConfig and normaliseRunsOn helper functions have been removed.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 8, 2026

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:

  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq .object.sha (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from pelikhan April 8, 2026 02:16
@pelikhan pelikhan marked this pull request as ready for review April 8, 2026 02:34
Copilot AI review requested due to automatic review settings April 8, 2026 02:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 polymorphic maintenance handling and runs_on as string-or-array).
  • Wires repo config into maintenance workflow generation to support custom runs-on values and an explicit maintenance: false opt-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

Comment on lines +170 to +192
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()
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +118 to +129
// 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
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
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.

3 participants