Skip to content

fix: unify on.permissions schema with shared github_actions_permissions ref#40064

Merged
pelikhan merged 2 commits into
mainfrom
copilot/fix-permissions-schema
Jun 18, 2026
Merged

fix: unify on.permissions schema with shared github_actions_permissions ref#40064
pelikhan merged 2 commits into
mainfrom
copilot/fix-permissions-schema

Conversation

Copilot AI commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

on.permissions used a hardcoded inline schema with 12 scopes and additionalProperties: false, omitting vulnerability-alerts (and attestations, copilot-requests, id-token, metadata, models, organization-projects). This caused gh aw compile to reject valid Dependabot pre-activation gates like:

on:
  schedule: daily
  workflow_dispatch:
  permissions:
    vulnerability-alerts: read   # ← rejected despite being valid
  steps:
    - id: check
      run: gh api /repos/${{ github.repository }}/dependabot/alerts?state=open ...

The top-level permissions: block already used $ref: #/$defs/github_actions_permissions, making the two schemas inconsistent.

Changes

  • main_workflow_schema.json — Replace on.permissions.oneOf[0] inline object with $ref: #/$defs/github_actions_permissions, unifying both permission blocks on the same shared definition. Adds a vulnerability-alerts: read example.

  • schema_errors.go — Add /on/permissions to knownFieldValidValues, knownFieldScopes, and knownFieldDocs so typos in on.permissions keys get "Did you mean?" suggestions and docs links, matching the behaviour already present for top-level /permissions.

  • Tests — Schema acceptance/rejection regression tests for vulnerability-alerts in on.permissions; new extractOnPermissions table case for the same scope.

…ns ref

- Replace inline on.permissions schema (which lacked vulnerability-alerts
  and other scopes) with $ref to shared #/$defs/github_actions_permissions
- Add /on/permissions to knownFieldScopes, knownFieldValidValues, and
  knownFieldDocs in schema_errors.go for better error hints
- Add tests for vulnerability-alerts in on.permissions (schema + extraction)
- Fix pre-existing testifylint warning in importinpututil/spec_test.go

Fixes #40063

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix permissions schema to support vulnerability-alerts fix: unify on.permissions schema with shared github_actions_permissions ref Jun 18, 2026
Copilot AI requested a review from pelikhan June 18, 2026 13:44
@pelikhan pelikhan marked this pull request as ready for review June 18, 2026 13:46
Copilot AI review requested due to automatic review settings June 18, 2026 13:46
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

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

No ADR enforcement needed: PR #40064 does not have the 'implementation' label (has_implementation_label=false) and has only 76 new lines of code in business logic directories (≤100 threshold).

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

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

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

Unifies the on.permissions JSON schema with the shared github_actions_permissions definition to accept additional valid GitHub Actions scopes (notably vulnerability-alerts) and aligns schema-error hinting for on.permissions with existing top-level permissions behavior.

Changes:

  • Replaced the inline on.permissions schema with a shared $defs/github_actions_permissions reference and added a vulnerability-alerts: read example.
  • Extended schema error hint metadata to include /on/permissions (valid values, scopes, docs link).
  • Added regression tests for vulnerability-alerts in on.permissions and extraction coverage in extractOnPermissions.
Show a summary per file
File Description
pkg/workflow/on_steps_test.go Adds extractOnPermissions test coverage for vulnerability-alerts.
pkg/parser/schemas/main_workflow_schema.json Switches on.permissions to use shared permissions definition and adds examples.
pkg/parser/schema_test.go Adds schema regression tests to accept vulnerability-alerts and reject unknown scopes in on.permissions.
pkg/parser/schema_errors.go Enables “Did you mean?” suggestions and docs links for /on/permissions unknown-scope errors.
pkg/importinpututil/spec_test.go Minor assertion style update using assert.Empty.

Copilot's findings

Tip

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

  • Files reviewed: 5/5 changed files
  • Comments generated: 2

Comment on lines 2131 to 2134
"permissions": {
"description": "Additional permissions for the pre-activation job. Use to declare extra scopes required by on.steps (e.g., issues: read for GitHub API calls in steps).",
"oneOf": [
{
"type": "object",
"description": "Map of permission scope to level",
"properties": {
"actions": {
"type": "string",
"enum": ["read", "write", "none"]
},
"checks": {
"type": "string",
"enum": ["read", "write", "none"]
},
"contents": {
"type": "string",
"enum": ["read", "write", "none"]
},
"deployments": {
"type": "string",
"enum": ["read", "write", "none"]
},
"discussions": {
"type": "string",
"enum": ["read", "write", "none"]
},
"issues": {
"type": "string",
"enum": ["read", "write", "none"]
},
"packages": {
"type": "string",
"enum": ["read", "write", "none"]
},
"pages": {
"type": "string",
"enum": ["read", "write", "none"]
},
"pull-requests": {
"type": "string",
"enum": ["read", "write", "none"]
},
"repository-projects": {
"type": "string",
"enum": ["read", "write", "none"]
},
"security-events": {
"type": "string",
"enum": ["read", "write", "none"]
},
"statuses": {
"type": "string",
"enum": ["read", "write", "none"]
}
},
"additionalProperties": false
}
],
"$ref": "#/$defs/github_actions_permissions",
"examples": [
Comment on lines +309 to 316
// Both /permissions and /on/permissions mirror #/$defs/github_actions_permissions in
// main_workflow_schema.json. Update this list when the schema changes.
var knownFieldValidValues = map[string]string{
// This list mirrors permissions.oneOf[1].properties in main_workflow_schema.json.
// Both entries mirror $defs/github_actions_permissions in main_workflow_schema.json.
// Update both when the schema changes.
"/permissions": "Valid permission scopes: actions, all, attestations, checks, copilot-requests, contents, deployments, discussions, id-token, issues, metadata, models, organization-projects, packages, pages, pull-requests, repository-projects, security-events, statuses, vulnerability-alerts",
"/permissions": "Valid permission scopes: actions, all, attestations, checks, copilot-requests, contents, deployments, discussions, id-token, issues, metadata, models, organization-projects, packages, pages, pull-requests, repository-projects, security-events, statuses, vulnerability-alerts",
"/on/permissions": "Valid permission scopes: actions, all, attestations, checks, copilot-requests, contents, deployments, discussions, id-token, issues, metadata, models, organization-projects, packages, pages, pull-requests, repository-projects, security-events, statuses, vulnerability-alerts",
}
@github-actions github-actions Bot mentioned this pull request Jun 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

⚠️ Test Quality Score: 70/100 — Acceptable

Analyzed 3 test(s): 3 design, 0 implementation, 0 guideline violation(s).

📊 Metrics & Test Classification (3 tests analyzed)
Metric Value
New/modified tests analyzed 3
✅ Design tests (behavioral contracts) 3 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 2 (67%)
Duplicate test clusters 0
Test inflation detected Yes — schema_test.go +43 lines; schema.go not changed in this PR (production change is JSON schema + schema_errors.go)
🚨 Coding-guideline violations 0
Test File Classification Issues Detected
TestValidateMainWorkflowFrontmatter_OnPermissionsVulnerabilityAlerts pkg/parser/schema_test.go:1981 ✅ Design
TestValidateMainWorkflowFrontmatter_OnPermissionsUnknownScopeRejected pkg/parser/schema_test.go:2006 ✅ Design
TestExtractOnPermissions (new row: on_permissions_vulnerability_alerts) pkg/workflow/on_steps_test.go:381 ✅ Design

Go: 3 (*_test.go); JavaScript: 0. No other languages detected.

Verdict

Check passed. 0% implementation tests (threshold: 30%). All three new test items directly verify observable behavioral contracts: schema acceptance of vulnerability-alerts, schema rejection of unknown scopes, and correct scope extraction — bilateral regression coverage for fix #40063. Score docked 10 pts for test inflation (43 lines added to schema_test.go; corresponding schema.go had 0 lines changed in this PR — the production behavior change lives in the JSON schema file, so this is expected and healthy).

References:

🧪 Test quality analysis by Test Quality Sentinel ·

@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. Test quality is acceptable — 0% of new tests are implementation tests (threshold: 30%).

@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 /improve-codebase-architecture — approving with non-blocking improvement suggestions.

📋 Key Themes & Highlights

Key Themes

  • Rejection test is under-asserted (schema_test.go): confirms err != nil but never exercises the knownFieldScopes["/on/permissions"] hint path added in schema_errors.go. A broken path mapping would be silent.
  • Duplicate scope lists (schema_errors.go): /permissions and /on/permissions now share the same $ref in JSON Schema but still carry identical 20-element slices in Go. Should share a single githubActionsPermissionScopes variable.
  • Acceptance coverage is scope-narrow: only vulnerability-alerts is tested; the other 6 previously-blocked scopes (attestations, copilot-requests, id-token, metadata, models, organization-projects) are not regression-pinned.

Positive Highlights

  • ✅ Core fix is surgical and correct — 57 lines of stale inline schema replaced by one $ref
  • ✅ Both acceptance and rejection regression tests are present
  • ✅ Independent coverage at the workflow-parse layer via TestExtractOnPermissions table case
  • schema_errors.go hint parity was correctly identified and added alongside the schema fix
  • ✅ PR description is clear, names the issue (#40063), and lists all changed components

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

Comment thread pkg/parser/schema_test.go
"engine": "copilot",
}
err := ValidateMainWorkflowFrontmatterWithSchemaAndLocation(frontmatter, "/tmp/gh-aw/on-permissions-unknown-scope-test.md")
if err == 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 rejection test confirms that err != nil, but does not verify that the error message actually contains the "Did you mean?" hints or docs URL added in schema_errors.go for /on/permissions.

If path detection is broken — e.g., the JSON schema path surfaced for an on.permissions violation is not exactly /on/permissions — the new knownFieldScopes and knownFieldDocs entries would be dead code, yet this test would still pass.

💡 Suggested assertion

Consider asserting the error message text, for example:

if err == nil {
    t.Error("unknown scope in on.permissions should be rejected")
}
if !strings.Contains(err.Error(), "vulnerability-alerts") {
    t.Errorf("expected \"Did you mean?\" hint with valid scopes in error, got: %v", err)
}

Or at minimum use assert.ErrorContains(t, err, "Valid permission scopes") to confirm the hint path fires.

"organization-projects", "packages", "pages", "pull-requests",
"repository-projects", "security-events", "statuses", "vulnerability-alerts",
},
"/on/permissions": {

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.

[/improve-codebase-architecture] The scope slice for /on/permissions is byte-for-byte identical to the /permissions slice, and both comments now say they mirror the same $ref. When a new scope is added to github_actions_permissions, there are four co-ordinated edits needed: two entries in knownFieldValidValues and two in knownFieldScopes.

Since the schema consolidation is the whole point of this PR, this is a good moment to consolidate the Go side too.

💡 Suggested refactor
// githubActionsPermissionScopes is the canonical scope list mirroring
// $defs/github_actions_permissions in main_workflow_schema.json.
// Update here when the schema changes.
var githubActionsPermissionScopes = []string{
    "actions", "all", "attestations", "checks", "copilot-requests", "contents", "deployments",
    "discussions", "id-token", "issues", "metadata", "models",
    "organization-projects", "packages", "pages", "pull-requests",
    "repository-projects", "security-events", "statuses", "vulnerability-alerts",
}

var knownFieldScopes = map[string][]string{
    "/permissions":    githubActionsPermissionScopes,
    "/on/permissions": githubActionsPermissionScopes,
}

Similarly, the long string in knownFieldValidValues could be built from this slice with strings.Join.

Comment thread pkg/parser/schema_test.go
"schedule": []any{map[string]any{"cron": "0 0 * * *"}},
"workflow_dispatch": nil,
"permissions": map[string]any{
"vulnerability-alerts": "read",

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 acceptance test pins vulnerability-alerts (the scope from the bug report), which is the right regression anchor. However, attestations, copilot-requests, id-token, metadata, models, and organization-projects were also blocked by the old inline schema and are now valid through the shared $ref — none of them have acceptance coverage.

Adding one or two to the acceptance test (e.g., attestations: write) would turn this into a broader schema-drift guard rather than a single-scope pin.

💡 Suggested addition
// covers a second scope that was previously blocked by the inline schema
"attestations": "write",

Or use a short table-driven loop over []string{"vulnerability-alerts", "attestations", "copilot-requests"} inside the test to keep it compact.

@pelikhan pelikhan merged commit b71973b into main Jun 18, 2026
78 of 90 checks passed
@pelikhan pelikhan deleted the copilot/fix-permissions-schema branch June 18, 2026 13:59
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.

on.permissions schema rejects vulnerability-alerts, blocking Dependabot-alert pre-activation gates

3 participants