Self-repository actions stage the entire repository and can fail on unrelated dangling symlinks
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 1.4k
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 24
Description
Main
Describe the bug
Using the self-repository action syntax:
- uses: $/.github/actions/example
causes the runner to download and stage the entire repository before the action executes, rather than only the referenced action directory.
This means that a tracked dangling symbolic link elsewhere in the repository can make action preparation fail, even though the action does not access that path. It also makes setup time and transfer size depend on the size of the whole repository. In the observed workflow, downloading and staging the repository added approximately 10 seconds before the action failed.
The dangling-symbolic-link failure is related to #3234. This report additionally covers its interaction with the new $/ syntax: loading a small self-repository action exposes it to every unrelated file in the repository and incurs the cost of staging the complete repository.
Feature announcement:
https://github.blog/changelog/2026-07-30-reference-same-repository-actions-with-self-repository-syntax/
To Reproduce
-
Add a minimal composite action at
.github/actions/example/action.yml:name: Example runs: using: composite steps: - shell: bash run: echo "Example action" -
Add and commit a dangling symbolic link outside the action directory:
mkdir -p unrelated/vendor ln -s ../missing/header.h unrelated/vendor/header.h git add unrelated/vendor/header.h git commit -m "Add reproduction" -
Reference the action before checkout:
jobs: reproduce: runs-on: ubuntu-24.04 steps: - uses: $/.github/actions/example -
Run the workflow.
-
Observe that the job fails while preparing actions, before the composite action executes.
Expected behavior
The runner should load the referenced action without staging unrelated repository contents. A dangling symbolic link outside .github/actions/example should not prevent that action from running.
Ideally, setup time and transfer size should be proportional to the referenced action and its declared dependencies, not to the size of the complete repository. If staging the whole repository remains necessary, dangling symbolic links should at least be preserved without requiring their targets to exist.
Runner Version and Platform
- Runner version:
2.336.0 - Platform: GitHub-hosted Linux runner
- Operating system: Ubuntu
24.04.4LTS - Runner image:
ubuntu-24.04, version20260720.247.2
What's not working?
The failure occurs during action download and staging, before any workflow step runs. A normal Git checkout on Linux can preserve the dangling symbolic link, but preparing the self-repository action fails while processing the unrelated path.
This also creates a performance cost for every $/ action because the complete repository is staged before the action executes. If the self-repository action subsequently performs a checkout, the repository transfer is duplicated.
Job Log Output
Sanitized example:
Download action repository 'owner/repository@<sha>'
Error: Could not find file '.../_staging/repository-<sha>/unrelated/vendor/header.h'.
Approximately 10 seconds were spent downloading and staging the repository (large monorepo) before this error was reported.
Runner and Worker's Diagnostic Logs
The failure was observed on a GitHub-hosted runner, so _diag logs are not available.
Suggested approach
Download and cache an archive scoped to the referenced action path instead of staging the complete repository. For example:
- uses: $/.github/actions/example
would initially make only .github/actions/example/** available.
This would:
- Isolate action preparation from unrelated repository contents.
- Avoid failures caused by dangling links outside the action directory.
- Reduce network transfer and disk use for large repositories.
- Avoid unnecessary duplicate transfer for actions that perform checkout.
- Permit caching by repository, commit, and action path.
Nested $/ action references could be resolved independently. An action that requires files outside its directory could declare additional paths explicitly in its metadata.
Azure Pipelines comparison
Azure Pipelines uses a different task-distribution model, but its approach may be useful here. Custom tasks are packaged independently, and the agent downloads and caches a task-specific ZIP using the task ID and version. Preparing a task does not require staging unrelated contents from the source repository.
GitHub could apply the same principle to self-repository actions while retaining commit-pinned $/ references: download the smallest artifact needed to run the selected action.
References:
- Azure Pipelines agent task download implementation:
https://github.com/microsoft/azure-pipelines-agent/blob/master/src/Agent.Worker/TaskManager.cs - Azure Pipelines custom task packaging:
https://learn.microsoft.com/en-us/azure/devops/extend/develop/add-build-task
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the minimal .github/actions/example/action.yml and the workflow step using $/ to reproduce the action download and staging failure. Trace the action preparation path that produces the _staging/repository-<sha>/unrelated/vendor/header.h error. Done means the referenced action runs without staging unrelated contents, dangling links outside its path do not fail preparation, and the regression is covered by an appropriate test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, github-actions
- Domain
- ci-cd, devops
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100