Summary
The copilot-setup-steps.yml workflow uses find .github/skills -name pyproject.toml -execdir uv sync \; to install Python dependencies for skills. GNU find does not propagate exit codes from -execdir commands — if uv sync fails for any pyproject.toml, find still returns exit code 0. This means broken or misconfigured Python skill dependencies will silently fail to install. The Copilot coding agent will then encounter runtime ImportError or ModuleNotFoundError with no prior indication of failure in the setup step output.
Additionally, the workflow's find command is missing the -type f flag that the devcontainer includes, which could cause unexpected behavior if a directory happened to match the -name pyproject.toml pattern.
Context
PR #921 added uv installation and skill dependency sync to copilot-setup-steps.yml, implementing the find -execdir pattern prescribed by issue #888. The pattern itself works correctly when all uv sync invocations succeed. The problem is exclusively about failure detection — there is no mechanism to surface or propagate uv sync failures.
Confirmed Behavior: find -execdir Does Not Propagate Exit Codes
This was verified via direct testing on GNU find (Ubuntu/WSL):
$ mkdir -p /tmp/test/a /tmp/test/b
$ touch /tmp/test/a/pyproject.toml /tmp/test/b/pyproject.toml
$ find /tmp/test -name pyproject.toml -execdir false \;
$ echo $?
0
Even though false always returns exit code 1, find returns 0. This is documented GNU find behavior — the exit code of find reflects whether find itself completed its traversal successfully, not whether the executed commands succeeded.
The GitHub Actions shell default (bash --noprofile --norc -eo pipefail) means set -e is active, but this is irrelevant because find's return code is 0 regardless of -execdir failures. The step will always pass, even when uv sync fails.
Current State vs Devcontainer
Workflow (copilot-setup-steps.yml, line 89):
find .github/skills -name pyproject.toml -execdir uv sync \;
Devcontainer (on-create.sh, line 95):
find .github/skills -name pyproject.toml -type f -execdir uv sync \;
Note the devcontainer includes -type f to restrict matches to regular files. The workflow omits this flag. While both commands share the same silent-failure behavior with -execdir, the -type f flag should be added for robustness regardless.
Current Impact
None today — zero skills currently have pyproject.toml files. All existing skills under .github/skills/ contain only .md, .ps1, .sh, .psm1, and .Tests.ps1 files. However, issue #868 tracks the first Python skill (PowerPoint automation), and when that or any future Python skill lands, this code path becomes active and the silent failure risk becomes real.
Changes Required
| File |
Change |
.github/workflows/copilot-setup-steps.yml |
Replace find -execdir with loop that propagates uv sync exit codes |
.github/workflows/copilot-setup-steps.yml |
Add -type f flag to the find command for robustness |
Recommended Implementation
Replace the single find-execdir line with a loop that captures and propagates failures:
echo "Syncing Python environments for skills..."
failed=0
while IFS= read -r -d '' f; do
dir="$(dirname "$f")"
echo "Installing dependencies in $dir"
if ! (cd "$dir" && uv sync); then
echo "::error::uv sync failed in $dir"
failed=1
fi
done < <(find .github/skills -name pyproject.toml -type f -print0)
if [[ "$failed" -ne 0 ]]; then
echo "::error::One or more skill dependency installations failed"
exit 1
fi
This approach:
- Uses
-print0 / read -d '' for safe handling of paths with spaces or special characters
- Includes
-type f to match only regular files (parity with devcontainer)
- Emits
::error:: annotations visible in the GitHub Actions UI per-directory failure
- Continues processing remaining skills even when one fails (reports all failures, not just the first)
- Exits with non-zero status if any
uv sync invocation fails
Alternative: Minimal Fix
If the loop approach is considered too verbose, a simpler alternative adds error propagation to the devcontainer pattern as well:
find .github/skills -name pyproject.toml -type f -print0 | \
xargs -0 -I {} bash -c 'cd "$(dirname "{}")" && uv sync'
However, this stops at the first failure and doesn't provide per-directory annotations. The loop approach is preferred.
Devcontainer Consideration
The devcontainer (on-create.sh, line 95) has the same silent-failure bug with -execdir. However, the devcontainer has set -euo pipefail at the top and is used interactively where failures are quickly noticed. A separate fix for on-create.sh may be warranted but is out of scope for this issue.
Acceptance Criteria
Related
Summary
The
copilot-setup-steps.ymlworkflow usesfind .github/skills -name pyproject.toml -execdir uv sync \;to install Python dependencies for skills. GNU find does not propagate exit codes from-execdircommands — ifuv syncfails for anypyproject.toml, find still returns exit code 0. This means broken or misconfigured Python skill dependencies will silently fail to install. The Copilot coding agent will then encounter runtimeImportErrororModuleNotFoundErrorwith no prior indication of failure in the setup step output.Additionally, the workflow's find command is missing the
-type fflag that the devcontainer includes, which could cause unexpected behavior if a directory happened to match the-name pyproject.tomlpattern.Context
PR #921 added uv installation and skill dependency sync to
copilot-setup-steps.yml, implementing thefind -execdirpattern prescribed by issue #888. The pattern itself works correctly when alluv syncinvocations succeed. The problem is exclusively about failure detection — there is no mechanism to surface or propagateuv syncfailures.Confirmed Behavior:
find -execdirDoes Not Propagate Exit CodesThis was verified via direct testing on GNU find (Ubuntu/WSL):
Even though
falsealways returns exit code 1,findreturns 0. This is documented GNU find behavior — the exit code of find reflects whether find itself completed its traversal successfully, not whether the executed commands succeeded.The GitHub Actions shell default (
bash --noprofile --norc -eo pipefail) meansset -eis active, but this is irrelevant because find's return code is 0 regardless of-execdirfailures. The step will always pass, even whenuv syncfails.Current State vs Devcontainer
Workflow (
copilot-setup-steps.yml, line 89):find .github/skills -name pyproject.toml -execdir uv sync \;Devcontainer (
on-create.sh, line 95):find .github/skills -name pyproject.toml -type f -execdir uv sync \;Note the devcontainer includes
-type fto restrict matches to regular files. The workflow omits this flag. While both commands share the same silent-failure behavior with-execdir, the-type fflag should be added for robustness regardless.Current Impact
None today — zero skills currently have
pyproject.tomlfiles. All existing skills under.github/skills/contain only.md,.ps1,.sh,.psm1, and.Tests.ps1files. However, issue #868 tracks the first Python skill (PowerPoint automation), and when that or any future Python skill lands, this code path becomes active and the silent failure risk becomes real.Changes Required
.github/workflows/copilot-setup-steps.ymlfind -execdirwith loop that propagatesuv syncexit codes.github/workflows/copilot-setup-steps.yml-type fflag to the find command for robustnessRecommended Implementation
Replace the single find-execdir line with a loop that captures and propagates failures:
This approach:
-print0/read -d ''for safe handling of paths with spaces or special characters-type fto match only regular files (parity with devcontainer)::error::annotations visible in the GitHub Actions UI per-directory failureuv syncinvocation failsAlternative: Minimal Fix
If the loop approach is considered too verbose, a simpler alternative adds error propagation to the devcontainer pattern as well:
However, this stops at the first failure and doesn't provide per-directory annotations. The loop approach is preferred.
Devcontainer Consideration
The devcontainer (
on-create.sh, line 95) has the same silent-failure bug with-execdir. However, the devcontainer hasset -euo pipefailat the top and is used interactively where failures are quickly noticed. A separate fix foron-create.shmay be warranted but is out of scope for this issue.Acceptance Criteria
uv syncfailures produce a non-zero exit code from the install stepuv syncproduces a visible::error::annotation in the Actions log-type fflag is present on the find commandpyproject.tomlfiles are processed even when one fails (no early abort)pyproject.tomlin a test run (manual verification step)Related
find -execdirpattern)find -execdir uv synccommand to copilot-setup-steps