Skip to content

feat: add dollar-self action reference syntax#4457

Draft
nodeselector wants to merge 7 commits into
actions:mainfrom
nodeselector:nodeselector/automatic-dollop
Draft

feat: add dollar-self action reference syntax#4457
nodeselector wants to merge 7 commits into
actions:mainfrom
nodeselector:nodeselector/automatic-dollop

Conversation

@nodeselector

@nodeselector nodeselector commented May 27, 2026

Copy link
Copy Markdown
Contributor

$/ — dollar-self action reference syntax

Adds $/path as a new uses: syntax meaning "this repo, at this SHA, at the given subpath." The containing YAML file determines which repo and SHA — so $/lib/helper inside external/foo@v1 resolves to external/foo@v1 with path lib/helper, not the workflow's root repo.

Why

Composite actions that ship multiple sub-actions in one repo currently hardcode owner/repo@ref to reference siblings. This creates a circular versioning problem — you can't cut a release tag until the YAML already references that tag. $/ breaks the cycle: siblings reference each other by path, and the ref is inherited from the caller.

What changed

ParsingPipelineTemplateConverter and WorkflowTemplateConverter detect $/ via a shared PipelineConstants.TryParseDollarSelfReference() helper. The parsed reference gets RepositoryType = "dollar-self" and Path = <subpath>.

ResolutionActionManager.ResolveDollarSelfReferences() rewrites dollar-self refs to concrete GitHub refs in-place:

  • Depth 0 (workflow-level steps): resolves to github.repository + github.sha
  • Depth > 0 (inside composites): resolves to the parent action's Name + Ref

After resolution, refs flow through the existing remote action download/prepare infrastructure. Pre/post steps work (unlike ./path local refs).

Batch path fixPrepareActionsRecursiveAsync (the batch resolution path) had a bug: nested composite sub-steps with $/ were passed to ResolveNewActionsAsync before dollar-self resolution, causing GetDownloadInfoLookupKey to throw InvalidOperationException. Fixed by pre-computing parent context per group and resolving $/ before the batch API call. The legacy path was not affected.

Feature flag

Gated behind actions_dollar_self_reference. When the flag is off, $/ references hit GetDownloadInfoLookupKey which throws with a clear error message. No silent misbehavior, no impact on existing workflows.

Tests

6 tests covering dollar-self resolution:

  • Depth-0 resolution (workflow-level $/)
  • Feature flag disabled → throws
  • Nested composite with $/ (batch path)
  • Nested composite with $/ (legacy path)
  • Cross-repo composite: $/ resolves to parent repo, not root
  • Three-level $/ chain (a→b→c)

Files

File What
Constants.cs DollarSelfReference feature flag
PipelineConstants.cs DollarSelfAlias, DollarSelfPrefix, TryParseDollarSelfReference()
WorkflowConstants.cs DollarSelfAlias
PipelineTemplateConverter.cs $/ parsing via shared helper
WorkflowTemplateConverter.cs $/ detection for step ID generation
ActionManager.cs ResolveDollarSelfReferences(), batch path fix
ActionManagerL0.cs 6 tests

nodeselector and others added 7 commits May 23, 2026 22:43
Implement support for the $/ self-referencing syntax in the actions
runner. This syntax resolves to 'this repo, at this SHA' based on the
containing YAML file, allowing composite actions to reference sibling
actions in the same repository without hardcoding versions.

Key changes:
- Parse $/path as RepositoryPathReference with RepositoryType='dollar-self'
- Resolve dollar-self refs in ActionManager before download:
  - Depth 0 (workflow level): github.repository + github.sha
  - Depth > 0 (composite): parent action's Name + Ref
- After resolution, refs flow through existing remote action infrastructure
- Pre/post steps supported (unlike ./path local refs)
- Feature-flagged via actions_dollar_self_reference

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
In PrepareActionsRecursiveAsync (the batch resolution path), nested
composite sub-steps with $/ references were passed to
ResolveNewActionsAsync before their dollar-self refs had been resolved.
GetDownloadInfoLookupKey throws InvalidOperationException for
unresolved DollarSelfAlias, crashing the batch path.

Fix: pre-compute parent context per group and call
ResolveDollarSelfReferences on each group BEFORE ResolveNewActionsAsync.
The existing ResolveDollarSelfReferences call at the top of the
recursive function becomes a no-op for already-resolved refs.

The legacy path (PrepareActionsRecursiveLegacyAsync) was not affected
because it recurses directly per-action without a batch pre-resolve step.

Tests added:
- Nested composite with $/ (batch path)
- Nested composite with $/ (legacy path)
- Cross-repo composite: $/ resolves to parent repo, not root
- Three-level $/ chain (a→b→c)
$/ is platform-agnostic YAML syntax, not a filesystem path. Remove the
$\\ StartsWith checks and TrimStart backslash handling from both
PipelineTemplateConverter and WorkflowTemplateConverter.
…eference

Extract the $/ prefix detection + path extraction into a single static
helper. Both PipelineTemplateConverter and WorkflowTemplateConverter now
use it instead of inline StartsWith/Substring logic.
The previous message said "This is a runner bug" — misleading when the
actual cause is the actions_dollar_self_reference feature flag not being
enabled. Now names the flag explicitly.
LoadAction re-parses action.yml from disk each time it is called,
producing fresh ActionStep objects with raw dollar-self refs. The
setup-time resolution in PrepareActionsRecursiveAsync operates on a
different set of objects, so the runtime composite steps still had
unresolved $/ refs — causing NullReferenceException when
CompositeActionHandler tried to use repoAction.Name (which is null
for dollar-self refs).

Fix: after loading composite steps in LoadAction, call
ResolveDollarSelfReferences using the parent action's Name and Ref.
This covers Steps, PreSteps, and PostSteps.
For reusable workflows, github.repository/sha point to the caller repo,
not the reusable workflow repo. job.workflow_repository/workflow_sha
point to the repo containing the workflow file — correct for both
regular and reusable workflows. Fall back to github context when
JobContext is unavailable.
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.

1 participant