Expose apm-version as an import input on shared/apm.md#1842
Conversation
Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
APM Review Panel:
|
| Persona | B | R | N | Takeaway |
|---|---|---|---|---|
| Python Architect | 0 | 2 | 2 | Clean additive schema extension; main risk is empty-string pass-through to apm-action when apm-version is unset -- correctness is an undocumented apm-action contract. |
| CLI Logging Expert | 0 | 2 | 1 | Clean additive workflow plumbing change with no Python CLI surface; two observability gaps: no ::notice when apm-version is pinned, and no format guard before value propagates to apm-action. |
| DevX UX Expert | 0 | 2 | 1 | Good input name; three UX gaps: directional header comment, silent empty-string passthrough contract, and missing format/error guidance for invalid versions. |
| Supply Chain Security Expert | 0 | 3 | 2 | Low-risk new attack surface (version is workflow-author-controlled); three findings on floating resolution, TOCTOU risk, and missing semver guard. |
| OSS Growth Hacker | 0 | 2 | 0 | Strong adoption unlock: removes the hand-edit-and-re-merge tax for CLI upgrades. Two discoverability gaps: no CHANGELOG entry and gh-aw.md docs omit the new input. |
| Doc Writer | 0 | 1 | 2 | Inline documentation is accurate and structurally consistent; one recommended fix on the misleading heading parenthetical, two nits on capitalization and example clarity. |
B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.
Top 5 follow-ups
- [Supply Chain Security Expert + Python Architect + DevX UX Expert + CLI Logging Expert] (blocking-severity) Add a conditional guard so apm-version is only forwarded to the apm-action
with:block when the input is non-empty -- installer.ts resolves'' || 'latest', so all non-opting consumers currently float to the latest CLI release, silently contradicting the PR's stated guarantee and the secure-by-default principle. - [CLI Logging Expert + DevX UX Expert + Doc Writer + Supply Chain Security Expert] Reword the header comment from '(newer than the action's default)' to a neutral override description (e.g. '(overrides the action's built-in default)') -- four panelists independently flagged this as misleading, and it is a one-line fix.
- [OSS Growth Hacker + Doc Writer] Add a CHANGELOG entry for the new apm-version import input and update gh-aw.md to surface it to incoming consumers -- user-visible import inputs require CHANGELOG coverage and gh-aw.md is the canonical consumer discovery surface.
- [Python Architect + DevX UX Expert + Supply Chain Security Expert] Document the accepted version string format (v-prefixed vs bare semver) and explicitly caution that 'latest' resolves dynamically at run time -- consumers will hit opaque downstream errors without format guidance and 'latest' introduces TOCTOU float risk that contradicts the feature's pinning intent.
- [CLI Logging Expert] Emit a
::noticelog line in the apm-prep compute step when apm-version is explicitly pinned -- consistent with the existing matrix observability pattern used for other key configuration dimensions.
Architecture
classDiagram
class ImportSchema {
+packages array
+appId string
+owner string
+target string
+apmVersion string
}
class ImportInputs {
+packages list
+target string
+apmVersion string
}
class CredentialGroup {
+id string
+kind string
+index int
+packages list
}
class PackStep {
+uses string
+apmVersion string
+dependencies string
+isolated bool
+pack bool
+target string
}
class RestoreStep {
+uses string
+apmVersion string
+bundlesFile string
}
class ApmAction {
+apmVersion string
+installCLI()
+packDependencies()
+restoreBundles()
}
ImportSchema --> ImportInputs : gh-aw compile
ImportInputs --> CredentialGroup : apm-prep normalises
CredentialGroup --> PackStep : matrix fan-out
PackStep --> ApmAction : invokes
RestoreStep --> ApmAction : invokes
ImportInputs ..> PackStep : apmVersion threads to
ImportInputs ..> RestoreStep : apmVersion threads to
flowchart TD
A[Consumer: imports shared/apm.md\nwith apm-version input] --> B[gh aw update: compile-time substitution]
B -->|import-inputs resolved| C[Compiled .lock.yml: apm-version inlined or empty]
C --> D[apm-prep job: compute credential matrix]
D -->|matrix fan-out| E[apm job per CredentialGroup]
E --> F[Pack via apm-action@v1.7.2]
F --> G[Bundle artifact: apm-groupid.tar.gz]
C --> H[pre-agent steps]
G -->|download| H
H --> I[Restore via apm-action@v1.7.2]
I --> J[Agent filesystem: .apm bundle unpacked]
style F fill:#d4edda
style I fill:#d4edda
Recommendation
The PR is correctly in draft. One behavioral correctness issue must be resolved before it leaves draft: the empty-string pass-through to apm-action, where installer.ts resolves '' || 'latest', silently floats all non-opting consumers to the latest CLI release -- the opposite of the stated guarantee. Once a conditional guard or explicit schema default is in place, three items should be folded in the same pass before leaving draft: reword the misleading header comment, add the CHANGELOG entry and gh-aw.md update, and document the accepted version format. The underlying feature design is clean and worth shipping fast once the behavioral fix lands.
Full per-persona findings
Python Architect
-
[recommended] Empty-string pass-through when apm-version is omitted is an undocumented behavioral contract with apm-action at
.github/workflows/shared/apm.md
import-schema declares apm-version withrequired: falseand nodefault:value. When a consumer omits apm-version, gh-aw substitutes an empty string; every compiled lock file for non-opting consumers will silently gainapm-version: ''on both apm-action invocations. Correctness depends entirely on apm-action@v1.7.2 treating''as 'use pinned default'; this is a behavioral contract not documented in the schema description.
Suggested: Document the empty-string semantics explicitly in the description field, or add a guard step in the workflow body that only forwards apm-version to thewith:block when the resolved input is non-empty. -
[recommended] Version string format (bare semver vs v-prefixed tag) is ambiguous in the docs at
.github/workflows/shared/apm.md
The header comment and schema description show '0.20.0' (bare semver) but release tags use 'v0.20.0' (v-prefixed); these forms may or may not be interchangeable depending on how apm-action resolves the version.
Suggested: Extend the description to state the accepted canonical form explicitly; if both are valid, say so. -
[nit] Header pin comment should note the minimum apm-action version that accepts the apm-version input at
.github/workflows/shared/apm.md
Consumers who vendor an older pin would silently have the input ignored (unknown inputs are not errors in GitHub Actions).
Suggested: Append to the pin-comment block:# apm-version input: accepted by microsoft/apm-action@v1.7.2 and above. -
[nit] In-repo compiled lock files are not regenerated by this PR
Expected for an opt-in input; lock files should be regenerated viagh aw updatepost-merge so consumers see the new behavior in the canonical reference.
CLI Logging Expert
-
[recommended] No
::noticeemitted when apm-version is pinned, breaking existing observability pattern at.github/workflows/shared/apm.md
The Compute APM credential-group matrix step already emits structured::noticelines for key configuration decisions. apm-version is equally decision-critical; without a companion notice, operators must spelunk into the apm-action step log to determine which CLI version was installed.
Suggested: Add a::noticeline in the apm-prep compute step that logs the resolved apm-version value -- either the pinned value or an explicit note that the apm-action default is in effect. -
[recommended] apm-version passed to apm-action with no format guard -- consumer typos produce opaque downstream errors at
.github/workflows/shared/apm.md
Every other validated input in the compute step uses early::error::with actionable remediation. apm-version receives no validation; typos like 'v0.20.0', '0.20', or 'latest' propagate silently. Empty-string behavior when apm-version is omitted is also unconfirmed.
Suggested: Add a semver format guard in the compute step and confirm with apm-action maintainers that an empty-string apm-version is equivalent to omitting the input. -
[nit] Header comment '(newer than the action's default)' implies version must be newer -- not technically required at
.github/workflows/shared/apm.md
Suggested: Change to '(overrides the action's built-in default)'.
DevX UX Expert
-
[recommended] Empty-string passthrough behaviour is an undocumented implicit contract with apm-action at
.github/workflows/shared/apm.md
When a consumer omits apm-version,${{ github.aw.import-inputs.apm-version }}resolves to''and is passed verbatim to both apm-actionwith:blocks. Whether apm-action treats''as 'use pinned default' is invisible to the consumer and fragile if the action changes its handling.
Suggested: Add a one-line note to the schema description, or guard at the step level so the key is only emitted when the consumer actually provided a value. -
[recommended] No format guidance or error signal documented for invalid version strings at
.github/workflows/shared/apm.md
The schema shows '0.20.0' but does not state whether v0.20.0 is accepted. Errors for non-existent versions surface deep in CI logs far from the import declaration -- unlike npm/pip/cargo which surface version errors close to the declaration.
Suggested: State whether v-prefix is accepted and add a note about what the consumer sees for an invalid version. -
[nit] Header comment says 'newer than the action's default' -- implies upgrade-only, which contradicts the input's bidirectional nature at
.github/workflows/shared/apm.md
Suggested: Drop the parenthetical or change to '# 5. Pin a specific apm CLI version:'.
Supply Chain Security Expert
-
[recommended] Schema omits
default:-- when apm-version is unset, installer.ts resolves 'latest' rather than the action's pinned default at.github/workflows/shared/apm.md
Thetargetschema sibling hasdefault: all;apm-versionhas nodefault:. In apm-action installer.ts:const apmVersionInput = (core.getInput('apm-version') || 'latest').trim()-- an empty string bypasses the action.yml default of 0.12.4 and falls into the 'latest' path, directly contradicting the PR description.
Suggested: Add a conditional guard so apm-version is only forwarded to thewith:block when the import-input is non-empty, preventing empty-string bypass of the action's own default. -
[recommended] Schema accepts 'latest' as a valid value without warning -- TOCTOU float risk at
.github/workflows/shared/apm.md
apm-action@v1.7.2 has a 'latest' branch that hits the GitHub Releases API at run time. A consumer passing 'latest' gets a different binary on every re-run, contradicting the pinning intent of the feature.
Suggested: Extend the schema description to document the float risk and caution against 'latest'. Consider apattern:constraint to reject the string at the schema layer. -
[recommended] No semver format guard at the shared-workflow layer -- version string flows raw to a URL constructor in installer.ts at
.github/workflows/shared/apm.md
The paralleltargetinput is validated with a regex before use.apm-versionhas no equivalent guard; the string is used to construct a release download URL and as a tool-cache key, both sensitive to malformed input.
Suggested: Add a schema-levelpatternconstraint (e.g.pattern: '^v?\d+\.\d+\.\d+[\w.+-]*$') so gh-aw rejects non-semver version strings before they reach the action. -
[nit] Both apm-action references use mutable tag v1.7.2 rather than a commit SHA (pre-existing) at
.github/workflows/shared/apm.md
Suggested: Replace with SHA-pinned refs:uses: microsoft/apm-action@<SHA> # v1.7.2. -
[nit] Example comment says 'newer than the action's default' -- implies an unenforced directional constraint at
.github/workflows/shared/apm.md
Suggested: Change to 'override the action's pinned default'.
OSS Growth Hacker
-
[recommended] No CHANGELOG entry for the user-visible apm-version import input at
CHANGELOG.md
CHANGELOG.md [Unreleased] is the primary surface where existing users discover new capabilities. Without an entry the feature cannot be included in the next release narrative.
Suggested: Add under [Unreleased] > ### Added: 'shared/apm.md now accepts an optionalapm-versioninput that pins the apm CLI version for both the Pack and Restore apm-action steps, survivinggh aw updatere-merges. (Expose apm-version as an import input on shared/apm.md #1842)' -
[recommended] gh-aw.md integration doc does not surface the apm-version input to incoming consumers at
docs/src/content/docs/integrations/gh-aw.md
docs/src/content/docs/integrations/gh-aw.md is the canonical docs entry point for the shared/apm.md integration; without a doc mention the feature is invisible to readers.
Suggested: Append to the Vendor callout: 'Once vendored, pin the apm CLI version by addingapm-version: "0.x.y"to the importwith:block. The pin survives futuregh aw updatere-merges.'
Doc Writer
-
[recommended] Example 5 heading parenthetical '(newer than the action's default)' implies apm-version is upgrade-only at
.github/workflows/shared/apm.md
Consumers pin for rollback, stability, and reproducibility -- not only to exceed the action default. The schema description correctly says 'Pin explicitly for reproducibility'; the heading contradicts it.
Suggested: Change to# 5. Pin the apm CLI version (overrides the action's bundled default): -
[nit] Capitalization inconsistency: new schema comment uses lowercase 'apm' where the adjacent comment uses uppercase 'APM' at
.github/workflows/shared/apm.md
Suggested: Change# apm CLI versionto# APM CLI version. -
[nit] Example 5 inherits
target: copilotfrom example 4, obscuring that apm-version is a standalone feature at.github/workflows/shared/apm.md
Suggested: Either removetarget: copilotto produce the minimal version-pinning example, or retitle to make the combination intentional.
Auth Expert -- inactive
PR #1842 touches only .github/workflows/shared/apm.md to thread an optional apm-version string input into apm-action invocations; no auth files, token resolution paths, or HTTP/git authorization headers are modified.
Test Coverage Expert -- inactive
documentation-only PR -- no runtime code paths to defend
Performance Expert -- inactive
PR changes only a workflow configuration file (apm-version input threading); no install pipeline, cache, or transport paths are touched.
This panel is advisory. It does not block merge. Re-apply the
panel-review label after addressing feedback to re-run.
Generated by PR Review Panel for issue #1842 · sonnet46 13.2M · ◷
There was a problem hiding this comment.
Pull request overview
This PR updates the vendorable shared workflow .github/workflows/shared/apm.md to expose an optional apm-version import input and thread it into both the pack and restore microsoft/apm-action invocations, enabling consumers to pin the APM CLI version without editing their vendored copy.
Changes:
- Added a new usage example (form 5) showing how to set
apm-version. - Extended
import-schemawith optionalapm-version: string. - Passed
apm-versioninto both the pack and restoremicrosoft/apm-action@v1.7.2steps.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/shared/apm.md | Adds apm-version as an import input and wires it into pack/restore apm-action steps, plus updates the header usage docs. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 2
| with: | ||
| apm-version: ${{ github.aw.import-inputs.apm-version }} | ||
| dependencies: ${{ steps.list.outputs.deps }} |
| - name: Restore APM packages (all bundles) | ||
| uses: microsoft/apm-action@v1.7.2 | ||
| with: | ||
| apm-version: ${{ github.aw.import-inputs.apm-version }} | ||
| bundles-file: /tmp/gh-aw/apm-bundle-list.txt |
Description
Consumers vendor
shared/apm.mdand import it from their agentic workflows, but the apm CLI version was pinned only viamicrosoft/apm-action's built-in default. Opting into a newer CLI (e.g. for package knowledge-base files or skill-bundle link-rewriting fixes) required hand-editing the vendored file — fragile, sincegh aw updatere-merges from upstream and--no-mergereverts it.This adds
apm-versionas a first-class, optional import input and threads it into bothapm-actioninvocations.apm-version(string) toimport-schema. Omit to fall through to the action's pinned default.apm-version: ${{ github.aw.import-inputs.apm-version }}into bothapm-actionsteps so the pack and restore CLI versions cannot skew.Consumers set it cleanly in their import, surviving
gh aw update:The
microsoft/apm-action@<tag>ref itself remains unparameterized (gh-aw SHA-pins the literaluses:ref at compile time); this covers the common case — a newer CLI on the existing action.Type of change
Testing
Validated the frontmatter YAML still parses and that
apm-versionis registered inimport-schema. No test infrastructure coversshared/apm.md; the change is additive and optional.Spec conformance (OpenAPM v0.1)
If this PR changes behaviour that an OpenAPM v0.1
req-XXXcovers,confirm the three-step ritual (see CONTRIBUTING.md "Adding or
changing a normative requirement"):
docs/src/content/docs/specs/openapm-v0.1.mdupdated(new/changed
<a id="req-XXX"></a>anchor + prose + Appendix Crow).
docs/src/content/docs/specs/manifests/openapm-v0.1.requirements.ymlupdated.
@pytest.mark.req("req-XXX")test undertests/spec_conformance/added or extended.CONFORMANCE.{md,json}regenerated viauv run --extra dev python -m tests.spec_conformance.gen_statementand committed.