Skip to content

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

Merged
pelikhan merged 5 commits intomainfrom
copilot/add-support-for-aw-json-config
Apr 8, 2026
Merged

feat: repo-level config via .github/workflows/aw.json#25227
pelikhan merged 5 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)
  • Schema enforces a safe pattern on runs_on values, blocking control characters and newlines
  • pkg/workflow/repo_config.go — loads, validates against schema, and deserialises into typed structs using JSON struct tags and json.Unmarshal
  • RunsOnValue implements json.Unmarshaler, accepting either a JSON string or array of strings
  • 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 (workflows using expires will emit a warning):

{
  "maintenance": false
}

Wiring

  • All hardcoded runs-on: ubuntu-slim in maintenance_workflow.go replaced with the configured value (defaulting to ubuntu-slim)
  • Multi-label runs-on values are serialised using json.Marshal to prevent YAML injection from special characters in runner labels
  • 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; any workflow that uses expires while maintenance is disabled receives a console warning

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.
@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented Apr 8, 2026

@copilot review coments

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 8, 2026

@copilot review coments

Addressed both review comments in b3b9f36:

  1. YAML injection in FormatRunsOn — For multi-label arrays, now uses json.Marshal([]string{...}) which properly escapes quotes, backslashes, and other special characters. The schema also gained a pattern constraint on runs_on string/array items that blocks control characters and newlines at input time, providing defence-in-depth.

  2. Silent expires no-op when maintenance disabled — Before returning early when maintenance: false, the function now iterates workflows and emits a console.FormatWarningMessage for any workflow that has expires configured, making the behaviour explicit rather than silent.

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:

@pelikhan pelikhan merged commit be553e3 into main Apr 8, 2026
85 checks passed
@pelikhan pelikhan deleted the copilot/add-support-for-aw-json-config branch April 8, 2026 04:46
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