Skip to content

Support source-to-destination mappings for inert nested packages #52770

Description

@Dongbumlee

Problem

Nested aw.yml packages intentionally treat .github/** entries as repository-root-relative (see #41790). This makes it impossible for a distribution repository to keep executable workflow assets inert under a nested package directory and install them into .github/** in the consuming repository.

A distribution layout such as:

repo/
  factory/
    aw.yml
    payload/
      workflows/controller.yml
      workflows/reviewer.md

needs to install as:

.github/workflows/controller.yml
.github/workflows/reviewer.md

The current manifest accepts only path strings and cannot express separate source and destination paths. Moving the source files to repository-root .github/workflows/ makes them active in the distribution repository, which is unsafe for packages containing deterministic controllers.

This is a feature request, not a regression report: current .github/** behavior matches ADR/PR #41790.

Expected capability

Allow package entries to declare a package-relative source and repository-relative destination while preserving existing string-entry behavior.

Illustrative syntax (maintainers may choose another shape):

includes:
  - source: payload/workflows/reviewer.md
    destination: .github/workflows/reviewer.md
    kind: agentic-workflow
  - source: payload/workflows/controller.yml
    destination: .github/workflows/controller.yml
    kind: action-workflow

Security and compatibility requirements

  • Existing string entries remain backward compatible.
  • source is resolved relative to the package root, including nested packages.
  • destination is resolved relative to the consuming repository root.
  • Reject absolute paths, .., symlinks, destination collisions, duplicate basenames, and writes outside approved namespaces.
  • Continue compiling agentic Markdown and copying deterministic YAML verbatim.
  • Never execute package-provided post-install shell code.
  • Preserve manifest-scoped source tracking for gh aw update.

Agentic implementation plan

  1. Schema and model

    • Update pkg/parser/schemas/aw_manifest_schema.json so includes accepts the current string form or an object containing validated source, destination, and optional kind.
    • Extend the package manifest model in pkg/cli/add_package_manifest.go with a resolved entry carrying both paths.
  2. Resolution

  3. Installation/update

    • Thread destination paths through WorkflowSpec and package install/update logic.
    • Compile .md entries using their installed destination name and copy raw .yml entries verbatim.
    • Detect multiple package entries targeting the same destination before any writes occur.
  4. Tests

    • Add nested-package tests where the remote fetch must request factory/payload/..., while installed output targets .github/workflows/....
    • Cover root packages, nested packages, mixed legacy/object entries, path traversal, absolute paths, collisions, symlinks, duplicate destinations, and update/source tracking.
    • Add an integration test for both gh aw add and gh aw add-wizard.
  5. Documentation/specification

    • Update the repository package manifest specification and reference docs.
    • Explicitly document the existing special rule: legacy string .github/** entries are repository-root-relative, while object-form source is package-relative.

Acceptance criteria

  • A nested package can keep all workflow sources outside repository-root .github/** and install them into the consuming repository's .github/workflows/**.
  • The distribution repository's workflows remain inert.
  • Existing manifests retain current behavior.
  • add, add-wizard, and update use identical mapping semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions