Skip to content

feat: resolve ${{ github.aw.import-inputs.* }} expressions in imports: frontmatter before nested import discovery#25241

Merged
pelikhan merged 5 commits intomainfrom
copilot/feat-allow-github-aw-import-inputs
Apr 8, 2026
Merged

feat: resolve ${{ github.aw.import-inputs.* }} expressions in imports: frontmatter before nested import discovery#25241
pelikhan merged 5 commits intomainfrom
copilot/feat-allow-github-aw-import-inputs

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

Shared workflows can use ${{ github.aw.import-inputs.* }} in tools:, safe-outputs:, etc., but expressions in the imports: section's with: values were silently passed as literal strings to nested imports — making multi-level workflow composition impossible.

Root cause

In import_bfs.go, the BFS loop parsed a file's frontmatter to discover nested imports from the raw content, before substituteImportInputsInContent was ever called. By the time substitution happened (inside extractAllImportFields), the nested import queue was already populated with unresolved expressions as literal input values.

Fix

  • pkg/parser/import_bfs.go — Parse the original content once, reuse that result to compute import-schema defaults via the new applyImportSchemaDefaultsFromFrontmatter helper, apply substitution, then re-parse only the substituted content so that nested-import discovery sees resolved with: values. This avoids the redundant YAML parse that the previous approach incurred.
  • pkg/parser/import_field_extractor.go — Extracted the schema-lookup logic from applyImportSchemaDefaults into a new applyImportSchemaDefaultsFromFrontmatter(frontmatter map[string]any, inputs map[string]any) helper that accepts an already-parsed frontmatter map, allowing callers to avoid a second YAML parse.
  • pkg/workflow/imports_inputs_test.go — Add TestImportInputsForwardedToNestedImports covering the multi-level composition scenario.
  • pkg/parser/import_inputs_integration_test.go — Add two //go:build integration tests (TestImportInputsForwardedToNestedImports_Integration and TestImportInputsMultipleForwardedToNestedImports_Integration) that exercise the parser API directly, verifying single-input and multi-input forwarding through an intermediate shared workflow.

Example (now works)

---
# shared/daily-report.md
import-schema:
  branch-name:
    type: string
    required: true

imports:
  - uses: shared/repo-memory.md
    with:
      branch-name: ${{ github.aw.import-inputs.branch-name }}  # ✅ now resolved
---

A consumer passing branch-name: "memory/my-workflow" will have that value correctly forwarded to shared/repo-memory.md.

…ted import discovery

Allow ${{ github.aw.import-inputs.* }} expressions in the imports: section
of shared workflows by applying expression substitution before parsing the
frontmatter for nested import discovery in the BFS traversal.

Previously, substituteImportInputsInContent was only called inside
extractAllImportFields (after nested imports had already been discovered),
so with: values containing ${{ github.aw.import-inputs.* }} were passed
as literal strings to nested imports. The fix applies the substitution
earlier, before ExtractFrontmatterFromContent is called for nested import
discovery, so that forwarded inputs are correctly resolved.

Adds TestImportInputsForwardedToNestedImports to verify the fix.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/50450d68-2884-4f6d-91d1-7b2afe54671c

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Feat: allow ${{ github.aw.import-inputs.* }} expressions in frontmatter imports section feat: resolve ${{ github.aw.import-inputs.* }} expressions in imports: frontmatter before nested import discovery Apr 8, 2026
Copilot AI requested a review from pelikhan April 8, 2026 05:37
@pelikhan pelikhan marked this pull request as ready for review April 8, 2026 05:40
Copilot AI review requested due to automatic review settings April 8, 2026 05:40
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

Fixes multi-level workflow composition by ensuring ${{ github.aw.import-inputs.* }} expressions inside an imported file’s imports: frontmatter are substituted before BFS nested-import discovery, so nested imports receive resolved concrete with: values instead of literal expression strings.

Changes:

  • Update BFS import processing to apply import-schema defaults + import-input substitution prior to frontmatter parsing for nested import discovery when the current import has inputs.
  • Add a regression test that composes consumer → intermediate → leaf workflows and verifies forwarded inputs are fully substituted in the compiled lock output.
Show a summary per file
File Description
pkg/parser/import_bfs.go Substitutes import inputs before frontmatter extraction so nested imports get resolved with: values during BFS discovery.
pkg/workflow/imports_inputs_test.go Adds test coverage for forwarding import-inputs through nested imports and ensuring no unresolved expressions remain.

Copilot's findings

Tip

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

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

Comment on lines +300 to +304
contentForFrontmatter := string(content)
if len(item.inputs) > 0 {
inputsWithDefaults := applyImportSchemaDefaults(contentForFrontmatter, item.inputs)
contentForFrontmatter = substituteImportInputsInContent(contentForFrontmatter, inputsWithDefaults)
}
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.

applyImportSchemaDefaults parses the file’s YAML frontmatter, and ExtractFrontmatterFromContent(contentForFrontmatter) parses it again immediately afterward. For large import graphs this adds avoidable YAML parsing overhead on every import-with-inputs. Consider refactoring to reuse a single parsed frontmatter/schema (e.g., extract import-schema once, compute defaults, substitute, then parse only what’s needed for nested import discovery), or adjust applyImportSchemaDefaults to accept an already-parsed frontmatter result.

Copilot uses AI. Check for mistakes.
@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented Apr 8, 2026

@copilot review comments, add integration tests

… import-inputs forwarding

- Refactor applyImportSchemaDefaults to delegate to a new
  applyImportSchemaDefaultsFromFrontmatter helper that works with an
  already-parsed frontmatter map, avoiding a redundant YAML parse.
- In the BFS loop, parse the original content once, then reuse that result
  to compute import-schema defaults before substitution (instead of calling
  applyImportSchemaDefaults which would parse again). Only the second parse
  (of substituted content) is necessary to see resolved nested imports.
- Add two integration tests in pkg/parser testing forwarding of single and
  multiple inputs through an intermediate shared workflow.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/2f21b3cc-a5e9-4e11-b5e7-21d18f0b3c87

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 8, 2026

@copilot review comments, add integration tests

Done in commit 21f82e1:

Review comment (double YAML parse): Refactored applyImportSchemaDefaults to delegate its schema-lookup logic to a new applyImportSchemaDefaultsFromFrontmatter helper that accepts an already-parsed map[string]any. The BFS loop now parses the original content once, reuses that result to compute defaults, applies substitution, then only re-parses the substituted content (needed to see the resolved with: values in nested imports). This eliminates the redundant parse that applyImportSchemaDefaults previously triggered internally.

Integration tests: Added pkg/parser/import_inputs_integration_test.go with two //go:build integration tests:

  • TestImportInputsForwardedToNestedImports_Integration — consumer → intermediate → leaf, verifies single input forwarded and leaf tools merged
  • TestImportInputsMultipleForwardedToNestedImports_Integration — same pattern with two inputs forwarded simultaneously

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/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha (http block)

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

🩺 Examination complete! CI Failure Doctor has delivered the diagnosis. Prescription issued! 💊

@github-actions github-actions bot removed the ci-doctor label Apr 8, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

🩺 CI Doctor Diagnosis

Checked 21f82e17bd56167df9b54ae5800daa43585cc1c0

Summary

Two checks are failing — build-wasm and test — both for the same root cause: stale golden test fixtures that reference Copilot CLI version 1.0.20, while the CI merge commit (PR branch merged with current main) now generates output with version 1.0.21.

Failing Checks

Check Conclusion Root Cause
build-wasm failure Golden files in testdata/TestWasmGolden_CompileFixtures/ expect 1.0.20, but compiled output produces 1.0.21
test failure Same root cause — TestWasmGolden_CompileFixtures subtests basic-copilot and with-imports fail
Detailed Analysis

Both jobs fail in TestWasmGolden_CompileFixtures (package github.com/github/gh-aw/pkg/workflow). The diff from the logs:

--- golden
+++ run
@@ -51,8 +51,8 @@
           GH_AW_INFO_ENGINE_ID: "copilot"
           GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
           GH_AW_INFO_MODEL: $\{\{ vars.GH_AW_MODEL_AGENT_COPILOT || 'auto' }}
-          GH_AW_INFO_VERSION: "1.0.20"
-          GH_AW_INFO_AGENT_VERSION: "1.0.20"
+          GH_AW_INFO_VERSION: "1.0.21"
+          GH_AW_INFO_AGENT_VERSION: "1.0.21"
-        run: \$\{RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh 1.0.20
+        run: \$\{RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh 1.0.21

Why the mismatch?

  • pkg/constants/version_constants.go on this PR branch still has DefaultCopilotVersion = "1.0.20"
  • pkg/constants/version_constants.go on main has been bumped to DefaultCopilotVersion = "1.0.21" (also DefaultClaudeCodeVersion: 2.1.92 → 2.1.94, DefaultFirewallVersion: v0.25.14 → v0.25.16)
  • GitHub Actions runs CI on the merge commit (this PR + current main), so the compiled output picks up 1.0.21 from main
  • But the golden files committed in this PR still have 1.0.20

Affected golden files:

  • pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden (lines 54, 55, 292)
  • pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden (lines 54, 55, 293)

This is not caused by the PR's changes (which only touch parser files: import_bfs.go, import_field_extractor.go, and associated tests). It's a rebase conflict with a version bump that landed on main after this branch was cut.

Recommended Fixes

  • Merge main into this branch (or rebase onto main) to pick up the version bump
  • Regenerate golden files by running:
    go test -v ./pkg/workflow -run='^TestWasmGolden_' -update
    or via the Makefile:
    make update-wasm-golden
  • Commit the updated golden files

Prevention Tips

When golden file tests cover version-stamped output, a rebase onto main after a version bump always requires regenerating the golden files. Consider adding a note in the PR checklist or a make check-golden CI step that hints at the update command when diffs are detected (this is already documented at the top of wasm_golden_test.go — just worth keeping in mind when rebasing long-lived branches).

Analysis Steps
  1. Read /tmp/ci-doctor/pr/summary.txt — identified 2 failing checks: build-wasm (job 70416738664) and test (job 70416738617), both in workflow run 24120729447
  2. Read /tmp/ci-doctor/pr/failed-checks.json to get job IDs
  3. Called get_job_logs with return_content=true, tail_lines=150 for both jobs in parallel
  4. Both logs showed identical failure: TestWasmGolden_CompileFixtures/basic-copilot and TestWasmGolden_CompileFixtures/with-imports failing with a version mismatch (1.0.20 in golden vs 1.0.21 generated)
  5. Read pkg/constants/version_constants.go on the PR branch → still shows 1.0.20
  6. Read pkg/workflow/wasm_golden_test.go to understand the test mechanism (uses charmbracelet/x/exp/golden, no overrides)
  7. Grepped for 1.0.21 in the repo → no matches (confirms the PR branch hasn't bumped it)
  8. Fetched pkg/constants/version_constants.go from main via GitHub MCP → confirmed DefaultCopilotVersion = "1.0.21" on main
  9. Root cause confirmed: version bump merged to main after this PR was branched; CI runs against merge commit which picks up 1.0.21, but golden files in PR still have 1.0.20

🩺 Diagnosis provided by CI Failure Doctor · ● 289.5K ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/ci-doctor.md@ea350161ad5dcc9624cf510f134c6a9e39a6f94d

@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented Apr 8, 2026

@copilot apply comments

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 8, 2026

@copilot apply comments

All review comments were already applied in commit 21f82e1:

  • Double YAML parse: Refactored to applyImportSchemaDefaultsFromFrontmatter which accepts an already-parsed map[string]any. The BFS loop now parses the original content once, reuses that result for defaults, then re-parses only the substituted content.
  • Integration tests: Added pkg/parser/import_inputs_integration_test.go with TestImportInputsForwardedToNestedImports_Integration and TestImportInputsMultipleForwardedToNestedImports_Integration, both passing.

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/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha (http block)

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

@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented Apr 8, 2026

@copilot apply #25241 (comment)

…thub-aw-import-inputs

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…(1.0.20 → 1.0.21)"

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/6324e02e-a20b-442a-9182-5475820588da

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 8, 2026

@copilot apply #25241 (comment)

Applied in commit a2dddf6: merged main and regenerated the golden files. The basic-copilot.golden and with-imports.golden files now reflect Copilot CLI 1.0.21.

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/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw FCpxM8syNrgG (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw rvm35a4x (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha ort-inputs (http block)
  • https://api.github.com/repos/github/gh-aw
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .visibility (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/-
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/- --jq .object.sha get .cfg ode_modules/.bin/sh http.https://git/usr/bin/gh (http block)

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

@pelikhan pelikhan merged commit adff490 into main Apr 8, 2026
54 of 56 checks passed
@pelikhan pelikhan deleted the copilot/feat-allow-github-aw-import-inputs branch April 8, 2026 12:26
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.

feat: allow ${{ github.aw.import-inputs.* }} expressions in frontmatter imports section

3 participants