Skip to content

Runtime import resolver does not handle repo-root-absolute paths (leading /) #24896

@bbonafed

Description

@bbonafed

Summary

PR #24501 fixed repo-root-relative path resolution in the compile-time ResolveIncludePath (pkg/parser/remote_fetch.go), but the runtime import resolver (actions/setup/js/runtime_import.cjs) was not updated to match. Paths like /.agents/skills/my-skill/instructions.md resolve correctly at compile time but fail at runtime with:

ERR_API: Failed to process runtime import for /.agents/skills/my-skill/instructions.md:
ERR_SYSTEM: Runtime import file not found: /home/runner/work/<repo>/<repo>/.github/workflows/.agents/skills/my-skill/instructions.md

The runtime handler prepends .github/workflows/ to the path instead of resolving from the repo root.

Root Cause

In actions/setup/js/runtime_import.cjs, processRuntimeImport (line ~739) has three branches for path resolution:

  1. Starts with .agents/ → resolve from GITHUB_WORKSPACE (repo root)
  2. Starts with .github/ → strip prefix, resolve under $WORKSPACE/.github
  3. Anything else → prepend workflows/, resolve under $WORKSPACE/.github

A path like /.agents/skills/my-skill/instructions.md has a leading /, so it does NOT match startsWith(".agents/"). It falls into branch 3, producing .github/workflows/.agents/skills/my-skill/instructions.md.

The compile-time resolver (remote_fetch.go) handles this correctly by stripping the leading / before the prefix checks — but the runtime resolver never got the equivalent fix.

Reproduction

  1. Place agent skill files in .agents/skills/ at the repo root
  2. In a workflow .md file, use:
    imports:
      - /.agents/skills/my-skill/instructions.md
  3. Compile with gh aw compile — succeeds, skill content is inlined
  4. The compiled .lock.yml contains {{#runtime-import /.agents/skills/my-skill/instructions.md}}
  5. When the workflow runs on GitHub Actions, the runtime import fails with the error above

gh-aw version: v0.67.1

Proposed Fix

In actions/setup/js/runtime_import.cjs, add a leading-/ strip before the existing prefix checks (around line 749):

// Strip leading "/" for repo-root-absolute paths (e.g. /.agents/skills/..., /.github/agents/...).
// After stripping, the existing .agents/ and .github/ prefix checks handle resolution correctly.
if (filepath.startsWith("/")) {
  const stripped = filepath.substring(1);
  if (stripped.startsWith(".agents/") || stripped.startsWith(".agents\\") ||
      stripped.startsWith(".github/") || stripped.startsWith(".github\\")) {
    filepath = stripped;
  }
}

This mirrors the behavior of ResolveIncludePath in pkg/parser/remote_fetch.go (lines 160-170) which was fixed in PR #24501. If the stripped path doesn't start with .agents/ or .github/, it falls through unchanged to the existing default branch — maintaining the same security restrictions.

Related

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions