Analysis
Following the officially-documented APM integration path (docs/src/content/docs/reference/dependencies.md):
APM is configured by importing the shared/apm.md workflow, which creates a dedicated apm job.
Reproduction is direct and confirmed on both v0.74.4 and v0.74.7 (latest pre-release at time of report) — identical error strings at identical (line, col) positions. Separately, the schema definitions on main (commit 8c2c89f, quoted verbatim below) still contain both restrictions, so main is also affected.
$ gh aw --version
gh aw version v0.74.4
$ gh aw add microsoft/apm/.github/workflows/shared/apm.md --dir shared --force
ℹ Overwriting existing file: …/shared/apm.md
✓ Added workflow: …/shared/apm.md
$ gh aw compile shared/apm.md
✗ Compiled 1 workflow(s): 1 error(s), 0 warning(s)
✗ Failed workflows:
✗ apm.md
shared/apm.md:120:7: error: Multiple schema validation failures:
- 'import-schema/apps' (line 120, col 7): Unknown property: properties
- 'jobs/apm/strategy' (line 272, col 14): 'matrix': got string, want object
117 | multiple orgs requiring different App installations.
118 | items:
119 | type: object
120 | properties:
^^^^^^^^^^
121 | id:
122 | type: string
123 | required: false
✗ compilation failed
Re-tested on v0.74.7 (same two errors, identical positions):
$ gh aw --version
gh aw version v0.74.7
$ gh aw compile shared/apm.md
✗ Compiled 1 workflow(s): 2 error(s) across 1 failed workflow(s), 0 warning(s)
✗ Failed workflows:
✗ apm.md
apm.md (2 error(s)):
🟡 MEDIUM PRIORITY:
1. .github/workflows/shared/apm.md:120:7: error: 'import-schema/apps' (line 120, col 7): Unknown property: properties
→ Fix this configuration issue and re-run `gh aw compile`.
2. .github/workflows/shared/apm.md:120:7: error: 'jobs/apm/strategy' (line 272, col 14): 'matrix': got string, want object
→ Fix this configuration issue and re-run `gh aw compile`.
Minimum-repro workflows isolating each gap independently of the full microsoft/apm shared workflow can be provided on request.
The file is microsoft/apm@main:.github/workflows/shared/apm.md (blob sha 47194cd1d976899e4d8c8131dc043d0342dbcf64). Both errors come from gh-aw's static schema. The import-schema block is gh-aw frontmatter (not GitHub Actions YAML), and the strategy.matrix construct is a standard GitHub Actions feature; together they're the form Microsoft ships for APM consumers via gh-aw's own documented integration.
The two restrictions are independent and both must be relaxed to unblock the integration; partial fixes leave shared/apm.md uncompilable even for consumers who use the no-credential or single-app forms (the unsupported constructs are in the shared workflow itself, not just in optional inputs).
Root cause 1 — import-schema.items only accepts primitive types
In pkg/parser/schemas/main_workflow_schema.json, properties.import-schema.additionalProperties.oneOf[0].properties.items is:
"items": {
"type": "object",
"description": "Schema for individual array elements. Typically {\"type\": \"string\"}.",
"properties": {
"type": {
"type": "string",
"enum": ["string", "number", "boolean"],
"description": "Type of each array item."
}
},
"additionalProperties": false
}
additionalProperties: false is what rejects properties: under items:, and the enum excludes object. The APM apps: input is an array of typed objects (cross-org GitHub App credential groups):
apps:
type: array
items:
type: object
properties:
id: { type: string, required: false }
app-id: { type: string, required: true }
private-key: { type: string, required: true }
owner: { type: string, required: false }
repositories: { type: string, required: false }
packages:
type: array
items: { type: string }
required: true
This array-of-objects shape is unrepresentable in today's import-schema grammar. import-schema already supports top-level object inputs (the second oneOf branch under additionalProperties, described in the schema as "Input parameter definition for object type (one level deep). Use 'properties' to declare the expected sub-fields."), but array items are limited to primitive element types (string / number / boolean), so an array input cannot declare object elements with nested properties.
Root cause 2 — strategy.matrix rejects dynamic expression form
In the same schema, $defs.job_strategy.matrix is:
"matrix": {
"type": "object",
"description": "Matrix variables for creating job variants. Each key defines a dimension of the matrix, with values as arrays (e.g., {os: [ubuntu-latest, windows-latest]}). Use 'include' to add extra configurations and 'exclude' to remove specific combinations.",
"additionalProperties": true
}
There is no oneOf branch for a string expression. The APM workflow uses GitHub Actions' standard dynamic matrix from a previous job's output:
apm:
needs: [activation, apm-prep]
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.apm-prep.outputs.matrix) }}
This is documented GitHub Actions behavior — the fromJSON "Example returning a JSON object" shows the whole strategy.matrix field form, i.e. matrix: ${{ fromJSON(needs.job1.outputs.matrix) }}. gh-aw rejects it at compile time even though the GitHub Actions runner accepts it at runtime.
Implementation Plan
Please implement the following changes:
-
Allow object-typed items in import-schema (pkg/parser/schemas/main_workflow_schema.json):
- Hoist the existing scalar/array input schema (currently
properties.import-schema.additionalProperties.oneOf[0]) into a reusable $defs.import-schema-input so it can be referenced from object-item sub-properties.
- Extend the
items sub-schema to a oneOf with the current primitive form or a new object form. The validator schema below is itself a JSON Schema, so it naturally uses the JSON-Schema keywords required and additionalProperties to constrain what users can write — that is unchanged. The point is to keep gh-aw's user-facing import-schema grammar on its existing per-property required: true|false convention; do not extend the user-facing grammar with JSON-Schema-style object-level required: [keys] or per-items additionalProperties semantics (those would be separate features and would distract from this bug):
"items": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": { "enum": ["string", "number", "boolean"] }
}
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": { "const": "object" },
"properties": {
"type": "object",
"additionalProperties": { "$ref": "#/$defs/import-schema-input" }
}
},
"required": ["type", "properties"]
}
]
}
- Scope: this is schema-acceptance only. It does not require changes to runtime input substitution. The microsoft/apm workflow uses the whole-array substitution form
${{ github.aw.import-inputs.apps }}, which already resolves correctly once the schema accepts the declaration. Indexed substitution like apps[0].owner is out of scope for this bug.
-
Allow dynamic strategy.matrix expressions (pkg/parser/schemas/main_workflow_schema.json):
- Change
$defs.job_strategy.matrix to a oneOf:
"matrix": {
"oneOf": [
{
"type": "object",
"additionalProperties": true,
"description": "Static matrix object."
},
{
"type": "string",
"pattern": "^\\s*\\$\\{\\{[\\s\\S]+\\}\\}\\s*$",
"description": "Dynamic matrix from a GitHub Actions expression, e.g. ${{ fromJSON(needs.prep.outputs.matrix) }}."
}
]
}
- The
pattern keeps validation tight: only ${{ ... }} expressions are accepted in string form, not arbitrary text.
-
Update validation error messages (pkg/workflow/schema_validation.go, pkg/parser/schema_errors.go):
- When
strategy.matrix is a non-expression string, keep the existing 'matrix': got string, want object recovery but extend the suggestion to also mention the dynamic form. Style:
- Example error:
'matrix': got plain string, want object or '${{ ... }}' expression. Example (static): matrix:\n os: [ubuntu-latest, windows-latest]. Example (dynamic): matrix: ${{ fromJSON(needs.prep.outputs.matrix) }}
- When
import-schema/<key> rejects properties: under items: for a primitive item type, suggest switching items.type to object (now allowed after Implementation Plan step 1 above).
-
Add tests (pkg/workflow/import_schema_test.go):
- Positive:
apps[] with object items + nested properties (mirroring the microsoft/apm shape) compiles. Verify whole-array substitution ${{ github.aw.import-inputs.apps }} still resolves end-to-end.
- Positive: an object item with a
required: true sub-property rejects a with: value that omits that sub-property at consumer-side validation (using gh-aw's existing per-property required convention).
- Negative: unknown sub-property inside an object item is still rejected (preserves the current strictness for typo detection).
- Regression: existing primitive-item tests stay green.
-
Add tests (pkg/workflow/compiler_yaml_test.go or the closest existing strategy/matrix test file):
- Positive:
matrix: ${{ fromJSON(needs.prep.outputs.matrix) }} compiles and round-trips into the lock file unchanged.
- Negative:
matrix: "not-an-expression" (plain non-expression string) still rejected by the new pattern.
- Regression: existing static
matrix: { os: [...], node: [...] } cases stay green.
-
Add a regression fixture (wired into pkg/workflow/shared_workflow_test.go):
- Preferred (low-friction): a minimal hand-written fixture that exercises just the
import-schema array-of-typed-objects shape and the dynamic matrix: form — independent of any upstream workflow and stable across microsoft/apm churn.
- Optional (end-to-end): if maintainers want full integration coverage, also vendor a pinned copy of
microsoft/apm@<sha>:.github/workflows/shared/apm.md as pkg/workflow/testdata/shared_workflow_apm.md. The pinned-vendoring approach trades maintenance and licensing surface for tighter regression guarantees on the documented integration.
-
Update documentation (paths TBD — please point me to the canonical files; I checked docs/src/content/docs/reference/dependencies.md exists, but did not find a dedicated import-schema.md):
- Wherever
import-schema is documented, add an example of object-typed items matching the microsoft/apm apps[] shape.
- Wherever job strategy /
matrix: is documented, add a short subsection on dynamic matrices and link to the GHA fromJSON example showing the whole-field form.
- In
docs/src/content/docs/reference/dependencies.md, note the minimum gh-aw version that supports the APM shared workflow once these changes ship.
-
Follow Guidelines:
- Run
make agent-finish before completing.
- Use the existing schema-validation error message style (
[what's wrong]. [what's expected]. [example]) per pkg/console conventions.
- No CLI surface change; no console formatting work expected beyond error messages.
Environment
| Field |
Value |
gh aw |
confirmed on v0.74.4 and v0.74.7 (latest at time of report) |
| OS |
macOS 25.4.0 (darwin) |
| Shell |
zsh |
| Source file |
microsoft/apm@main:.github/workflows/shared/apm.md, blob sha 47194cd1d976899e4d8c8131dc043d0342dbcf64 |
| Doc followed |
docs/src/content/docs/reference/dependencies.md @ commit 8c2c89ffa00af3d2988d2fd93a2d4ebcdf03c900 |
Analysis
Following the officially-documented APM integration path (
docs/src/content/docs/reference/dependencies.md):Reproduction is direct and confirmed on both v0.74.4 and v0.74.7 (latest pre-release at time of report) — identical error strings at identical
(line, col)positions. Separately, the schema definitions onmain(commit8c2c89f, quoted verbatim below) still contain both restrictions, somainis also affected.Re-tested on v0.74.7 (same two errors, identical positions):
Minimum-repro workflows isolating each gap independently of the full microsoft/apm shared workflow can be provided on request.
The file is
microsoft/apm@main:.github/workflows/shared/apm.md(blob sha47194cd1d976899e4d8c8131dc043d0342dbcf64). Both errors come from gh-aw's static schema. Theimport-schemablock is gh-aw frontmatter (not GitHub Actions YAML), and thestrategy.matrixconstruct is a standard GitHub Actions feature; together they're the form Microsoft ships for APM consumers via gh-aw's own documented integration.The two restrictions are independent and both must be relaxed to unblock the integration; partial fixes leave
shared/apm.mduncompilable even for consumers who use the no-credential or single-app forms (the unsupported constructs are in the shared workflow itself, not just in optional inputs).Root cause 1 —
import-schema.itemsonly accepts primitive typesIn
pkg/parser/schemas/main_workflow_schema.json,properties.import-schema.additionalProperties.oneOf[0].properties.itemsis:additionalProperties: falseis what rejectsproperties:underitems:, and theenumexcludesobject. The APMapps:input is an array of typed objects (cross-org GitHub App credential groups):This array-of-objects shape is unrepresentable in today's
import-schemagrammar.import-schemaalready supports top-level object inputs (the secondoneOfbranch underadditionalProperties, described in the schema as "Input parameter definition for object type (one level deep). Use 'properties' to declare the expected sub-fields."), but array items are limited to primitive element types (string/number/boolean), so anarrayinput cannot declare object elements with nestedproperties.Root cause 2 —
strategy.matrixrejects dynamic expression formIn the same schema,
$defs.job_strategy.matrixis:There is no
oneOfbranch for a string expression. The APM workflow uses GitHub Actions' standard dynamic matrix from a previous job's output:This is documented GitHub Actions behavior — the
fromJSON"Example returning a JSON object" shows the wholestrategy.matrixfield form, i.e.matrix: ${{ fromJSON(needs.job1.outputs.matrix) }}. gh-aw rejects it at compile time even though the GitHub Actions runner accepts it at runtime.Implementation Plan
Please implement the following changes:
Allow object-typed
itemsinimport-schema(pkg/parser/schemas/main_workflow_schema.json):properties.import-schema.additionalProperties.oneOf[0]) into a reusable$defs.import-schema-inputso it can be referenced from object-item sub-properties.itemssub-schema to aoneOfwith the current primitive form or a new object form. The validator schema below is itself a JSON Schema, so it naturally uses the JSON-Schema keywordsrequiredandadditionalPropertiesto constrain what users can write — that is unchanged. The point is to keep gh-aw's user-facing import-schema grammar on its existing per-propertyrequired: true|falseconvention; do not extend the user-facing grammar with JSON-Schema-style object-levelrequired: [keys]or per-itemsadditionalPropertiessemantics (those would be separate features and would distract from this bug):${{ github.aw.import-inputs.apps }}, which already resolves correctly once the schema accepts the declaration. Indexed substitution likeapps[0].owneris out of scope for this bug.Allow dynamic
strategy.matrixexpressions (pkg/parser/schemas/main_workflow_schema.json):$defs.job_strategy.matrixto aoneOf:patternkeeps validation tight: only${{ ... }}expressions are accepted in string form, not arbitrary text.Update validation error messages (
pkg/workflow/schema_validation.go,pkg/parser/schema_errors.go):strategy.matrixis a non-expression string, keep the existing'matrix': got string, want objectrecovery but extend the suggestion to also mention the dynamic form. Style:'matrix': got plain string, want object or '${{ ... }}' expression. Example (static): matrix:\n os: [ubuntu-latest, windows-latest]. Example (dynamic): matrix: ${{ fromJSON(needs.prep.outputs.matrix) }}import-schema/<key>rejectsproperties:underitems:for a primitive item type, suggest switchingitems.typetoobject(now allowed after Implementation Plan step 1 above).Add tests (
pkg/workflow/import_schema_test.go):apps[]with object items + nestedproperties(mirroring the microsoft/apm shape) compiles. Verify whole-array substitution${{ github.aw.import-inputs.apps }}still resolves end-to-end.required: truesub-property rejects awith:value that omits that sub-property at consumer-side validation (using gh-aw's existing per-propertyrequiredconvention).Add tests (
pkg/workflow/compiler_yaml_test.goor the closest existing strategy/matrix test file):matrix: ${{ fromJSON(needs.prep.outputs.matrix) }}compiles and round-trips into the lock file unchanged.matrix: "not-an-expression"(plain non-expression string) still rejected by the newpattern.matrix: { os: [...], node: [...] }cases stay green.Add a regression fixture (wired into
pkg/workflow/shared_workflow_test.go):import-schemaarray-of-typed-objects shape and the dynamicmatrix:form — independent of any upstream workflow and stable across microsoft/apm churn.microsoft/apm@<sha>:.github/workflows/shared/apm.mdaspkg/workflow/testdata/shared_workflow_apm.md. The pinned-vendoring approach trades maintenance and licensing surface for tighter regression guarantees on the documented integration.Update documentation (paths TBD — please point me to the canonical files; I checked
docs/src/content/docs/reference/dependencies.mdexists, but did not find a dedicatedimport-schema.md):import-schemais documented, add an example of object-typeditemsmatching the microsoft/apmapps[]shape.matrix:is documented, add a short subsection on dynamic matrices and link to the GHAfromJSONexample showing the whole-field form.docs/src/content/docs/reference/dependencies.md, note the minimum gh-aw version that supports the APM shared workflow once these changes ship.Follow Guidelines:
make agent-finishbefore completing.[what's wrong]. [what's expected]. [example]) perpkg/consoleconventions.Environment
gh awv0.74.4andv0.74.7(latest at time of report)microsoft/apm@main:.github/workflows/shared/apm.md, blob sha47194cd1d976899e4d8c8131dc043d0342dbcf64docs/src/content/docs/reference/dependencies.md@ commit8c2c89ffa00af3d2988d2fd93a2d4ebcdf03c900