fix(setup): clean up root-owned /tmp/awf-*-chroot-home directories by Copilot · Pull Request #41852 · github/gh-aw · GitHub
Skip to content

fix(setup): clean up root-owned /tmp/awf-*-chroot-home directories#41852

Merged
pelikhan merged 5 commits into
mainfrom
copilot/aw-fix-code-simplifier-failure
Jun 27, 2026
Merged

fix(setup): clean up root-owned /tmp/awf-*-chroot-home directories#41852
pelikhan merged 5 commits into
mainfrom
copilot/aw-fix-code-simplifier-failure

Conversation

Copilot AI commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

When AWF ran with sudo -E awf --enable-host-access, it created /tmp/awf-{timestamp}-chroot-home directories with root-owned files. On shared runners these persisted across jobs; the Copilot CLI's rimrafSync (Node.js-internal) ran as the non-root runner user and failed:

errno: -13, code: 'EACCES', syscall: 'unlink',
path: '/tmp/awf-1782534983684-chroot-home/.aws/config'

Changes

  • actions/setup/post.js — after cleaning /tmp/gh-aw, switch chroot-home cleanup to sudo find ... -print + sudo find ... -exec rm -rf -- {} + so behavior is explicit and logs distinguish:
    • inspection failure
    • no directories found
    • cleanup success (with count)
    • cleanup failure
  • actions/setup/clean.sh — mirror the same find-based cleanup behavior in script mode, including explicit “none found” and failure messages
  • actions/setup/sh/install_copilot_cli.sh — keep pre-run cleanup and add -- in rm -rf -- {} for option-safety
  • actions/setup/js/chroot_home_cleanup.test.js — add coverage for chroot-home cleanup paths in both post.js and clean.sh (no-match and successful cleanup branches)

These changes keep cleanup best-effort while making the behavior and logging accurate and adding test coverage for the new cleanup paths.

Copilot AI and others added 2 commits June 27, 2026 05:59
When AWF ran with --enable-host-access (using sudo -E awf), it created
/tmp/awf-{timestamp}-chroot-home directories containing root-owned files.
The Copilot CLI cleanup path (rimrafSync via Node.js internals) ran as the
non-root runner user and failed with EACCES, causing the code-simplifier
workflow to report 'engine terminated unexpectedly'.

Add sudo rm -rf cleanup for /tmp/awf-*-chroot-home in:
- actions/setup/post.js (post-run cleanup action)
- actions/setup/clean.sh (script-mode mirror of post.js)
- actions/setup/sh/install_copilot_cli.sh (pre-run, alongside existing
  sudo chown fix for the .copilot directory)

Closes #41842

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
- Remove redundant nested sudo in install_copilot_cli.sh find command
- Rename awfChrootHomeCleanup to awfChrootHomeCleanupResult in post.js
- Clarify log message for non-zero exit status in post.js

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix code simplifier workflow failure fix(setup): clean up root-owned /tmp/awf-*-chroot-home directories Jun 27, 2026
Copilot AI requested a review from pelikhan June 27, 2026 06:01
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage — §28282332784

Field Value
Category bug
Risk medium
Score 48/100 (impact 28 + urgency 15 + quality 5)
Action defer

Rationale: Draft PR fixing root-owned chroot-home cleanup on shared runners (4 files). No CI yet. Promote from draft and ensure CI passes before review.

Generated by 🔧 PR Triage Agent · 74.7 AIC · ⌖ 8.27 AIC · ⊞ 5.4K ·

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

No test files were added or modified in this PR. Test Quality Sentinel skipped. Changed files: actions/setup/clean.sh, actions/setup/post.js, actions/setup/sh/install_copilot_cli.sh, .changeset/patch-fix-awf-chroot-home-cleanup.md

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100).

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses cleanup failures on shared GitHub-hosted runners caused by root-owned AWF chroot-home directories (/tmp/awf-*-chroot-home) left behind after running AWF with --enable-host-access. The change adds best-effort, sudo-based cleanup paths so subsequent runs don’t fail with EACCES during Copilot CLI cleanup.

Changes:

  • Add cleanup for /tmp/awf-*-chroot-home in the setup action post step (actions/setup/post.js).
  • Mirror the same cleanup behavior for script-mode runs (actions/setup/clean.sh).
  • Add pre-run cleanup in the Copilot CLI install script to prevent stale state before the agent starts (actions/setup/sh/install_copilot_cli.sh).
Show a summary per file
File Description
actions/setup/sh/install_copilot_cli.sh Pre-run removal of stale /tmp/awf-*-chroot-home directories to avoid Copilot CLI EACCES cleanup failures.
actions/setup/post.js Post-job cleanup now also attempts to remove AWF chroot-home remnants under /tmp.
actions/setup/clean.sh Script-mode equivalent cleanup now includes removing AWF chroot-home remnants under /tmp.
.changeset/patch-fix-awf-chroot-home-cleanup.md Patch changeset documenting the runner cleanup fix.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment thread actions/setup/post.js
Comment on lines +123 to +133
// Clean up AWF chroot home directories under /tmp (e.g. /tmp/awf-*-chroot-home).
// These are created by AWF when running with --enable-host-access on GitHub-hosted runners.
// Files inside may be owned by root (written by Docker containers or privileged AWF processes),
// causing EACCES failures if cleanup is attempted without sudo. We use sudo rm -rf to handle
// these root-owned remnants; failures are non-fatal since cleanup is best-effort.
const awfChrootHomeCleanupResult = spawnSync("sudo", ["sh", "-c", "rm -rf /tmp/awf-*-chroot-home"], { stdio: "inherit" });
if (awfChrootHomeCleanupResult.status === 0) {
console.log("Cleaned up /tmp/awf-*-chroot-home");
} else {
console.log("Failed to clean /tmp/awf-*-chroot-home or no directories found");
}
Comment thread actions/setup/clean.sh Outdated
Comment on lines +48 to +50
if sudo rm -rf /tmp/awf-*-chroot-home 2>/dev/null; then
echo "Cleaned up /tmp/awf-*-chroot-home (sudo)"
fi
Comment thread actions/setup/sh/install_copilot_cli.sh Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /diagnose, /tdd, and /zoom-out — commenting with suggestions, no blocking issues.

📋 Key Themes & Highlights

Key Themes

  • Silent failure paths: post.js uses console.log for cleanup failures (not warn/error), and the spawnSync error property is not inspected — spawn failures fall silently into the else branch.
  • clean.sh inconsistencies: No else warning branch when sudo rm -rf fails, and uses a shell-glob rm -rf while install_copilot_cli.sh uses the safer find-based approach.
  • No regression test: The fixed EACCES code path has no accompanying test; a future refactor could silently reintroduce the failure.

Positive Highlights

  • ✅ Root cause correctly identified and addressed at three call sites (post.js, clean.sh, install_copilot_cli.sh).
  • ✅ Mirrors the existing sudo rm -rf pattern already used for /tmp/gh-aw — consistent idiom.
  • ✅ Non-fatal / best-effort design is appropriate; failures are logged, not thrown.
  • ✅ Detailed comments in each file explain the sudo requirement and why root-owned files appear — great for future maintainers.
  • ✅ Changeset entry is clear and accurate.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 57.6 AIC · ⌖ 8.18 AIC · ⊞ 6.6K

Comment thread actions/setup/post.js Outdated
// Files inside may be owned by root (written by Docker containers or privileged AWF processes),
// causing EACCES failures if cleanup is attempted without sudo. We use sudo rm -rf to handle
// these root-owned remnants; failures are non-fatal since cleanup is best-effort.
const awfChrootHomeCleanupResult = spawnSync("sudo", ["sh", "-c", "rm -rf /tmp/awf-*-chroot-home"], { stdio: "inherit" });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/diagnose] spawnSync can fail to spawn the child process entirely (e.g., if sudo is absent from PATH), returning { error: Error, status: null }. Checking only .status means a spawn-level failure silently falls into the else branch without surfacing the underlying error.

💡 Suggested fix
const awfChrootHomeCleanupResult = spawnSync(
  "sudo", ["sh", "-c", "rm -rf /tmp/awf-*-chroot-home"],
  { stdio: "inherit" }
);
if (awfChrootHomeCleanupResult.error) {
  console.warn(`Warning: failed to spawn AWF chroot-home cleanup: ${awfChrootHomeCleanupResult.error.message}`);
} else if (awfChrootHomeCleanupResult.status === 0) {
  console.log("Cleaned up /tmp/awf-*-chroot-home");
} else {
  console.warn(`Warning: AWF chroot-home cleanup exited with status ${awfChrootHomeCleanupResult.status}`);
}

This mirrors the defensive err.message pattern already used in the rimrafSync error handler above.

@copilot please address this.

Comment thread actions/setup/post.js Outdated
if (awfChrootHomeCleanupResult.status === 0) {
console.log("Cleaned up /tmp/awf-*-chroot-home");
} else {
console.log("Failed to clean /tmp/awf-*-chroot-home or no directories found");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/diagnose] The failure branch uses console.log — so a cleanup failure is indistinguishable from normal output in runner logs. Use console.warn (or console.error) to make this visible when scanning logs for problems.

💡 Suggested change
} else {
  console.warn(`Warning: failed to clean /tmp/awf-*-chroot-home (exit ${awfChrootHomeCleanupResult.status})`);
}

The existing rimrafSync failure path in this file already uses console.error("Warning: ...") — aligning here keeps the log severity consistent.

@copilot please address this.

Comment thread actions/setup/clean.sh
# causing EACCES failures if cleanup is attempted without sudo.
if sudo rm -rf /tmp/awf-*-chroot-home 2>/dev/null; then
echo "Cleaned up /tmp/awf-*-chroot-home (sudo)"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/diagnose] The if block silently ignores a non-zero exit code — 2>/dev/null already suppresses stderr, and there is no else branch. post.js at least logs a message on failure; clean.sh drops the signal entirely, making future debugging harder.

💡 Suggested change
if sudo rm -rf /tmp/awf-*-chroot-home 2>/dev/null; then
  echo "Cleaned up /tmp/awf-*-chroot-home (sudo)"
else
  echo "Warning: failed to clean /tmp/awf-*-chroot-home" >&2
fi

This mirrors the echo "Warning: failed to clean up ..." >&2 pattern already used at line 41 of this file.

@copilot please address this.

Comment thread actions/setup/clean.sh Outdated
# These are created by AWF when running with --enable-host-access on GitHub-hosted runners.
# Files inside may be owned by root (written by Docker containers or privileged AWF processes),
# causing EACCES failures if cleanup is attempted without sudo.
if sudo rm -rf /tmp/awf-*-chroot-home 2>/dev/null; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/zoom-out] clean.sh uses a shell-glob rm -rf approach while install_copilot_cli.sh (line 54) uses the safer sudo find /tmp -maxdepth 1 -name 'awf-*-chroot-home' -type d -exec rm -rf {} +. The find-based approach is more explicit (only removes directories, never ambiguous if glob expands to a file), and it is already established in this PR. Aligning both scripts reduces divergence.

💡 Suggested change
# Remove AWF chroot home directories under /tmp (e.g. /tmp/awf-*-chroot-home).
if sudo find /tmp -maxdepth 1 -name 'awf-*-chroot-home' -type d -exec rm -rf {} + 2>/dev/null; then
  echo "Cleaned up /tmp/awf-*-chroot-home (sudo)"
else
  echo "Warning: failed to clean /tmp/awf-*-chroot-home" >&2
fi

@copilot please address this.

Comment thread actions/setup/post.js Outdated
// Files inside may be owned by root (written by Docker containers or privileged AWF processes),
// causing EACCES failures if cleanup is attempted without sudo. We use sudo rm -rf to handle
// these root-owned remnants; failures are non-fatal since cleanup is best-effort.
const awfChrootHomeCleanupResult = spawnSync("sudo", ["sh", "-c", "rm -rf /tmp/awf-*-chroot-home"], { stdio: "inherit" });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] This bug fix has no accompanying regression test. Without one, the EACCES failure path could silently return if this cleanup code is ever refactored or removed. A unit test that mocks spawnSync and asserts it is called with the correct sudo arguments would guard against regressions.

💡 Sketch of a regression test
it('calls sudo rm -rf for awf chroot-home dirs on cleanup', () => {
  const spawnSyncMock = jest.fn().mockReturnValue({ status: 0, error: null });
  // inject mock and run the cleanup step
  expect(spawnSyncMock).toHaveBeenCalledWith(
    'sudo',
    ['sh', '-c', 'rm -rf /tmp/awf-*-chroot-home'],
    expect.objectContaining({ stdio: 'inherit' })
  );
});

Even a lightweight smoke test prevents silent regressions.

@copilot please address this.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • patchdiff.githubusercontent.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "patchdiff.githubusercontent.com"

See Network Configuration for more information.

🔎 Code quality review by PR Code Quality Reviewer · 91.1 AIC · ⌖ 6.91 AIC · ⊞ 5.2K

Comment thread actions/setup/post.js Outdated
if (awfChrootHomeCleanupResult.status === 0) {
console.log("Cleaned up /tmp/awf-*-chroot-home");
} else {
console.log("Failed to clean /tmp/awf-*-chroot-home or no directories found");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failure path uses console.log instead of console.error, so a genuine sudo failure blends into normal output and won't surface as an error in CI log scanning or ::error:: annotations.

💡 Suggested fix

Change the else branch to match the error-logging convention already used for the tmpDir cleanup on line 119:

} else {
  console.error("Failed to clean /tmp/awf-*-chroot-home: sudo returned non-zero");
}

Note: the success branch also needs attention (flagged separately) — when no directories match, rm -rf with -f exits 0, so the else branch is only reachable when sudo itself fails. That makes correct error logging here especially important for diagnosing sudo policy issues on runners.

Comment thread actions/setup/clean.sh
# causing EACCES failures if cleanup is attempted without sudo.
if sudo rm -rf /tmp/awf-*-chroot-home 2>/dev/null; then
echo "Cleaned up /tmp/awf-*-chroot-home (sudo)"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When sudo rm -rf returns non-zero (actual sudo failure, not the no-match case), there is no warning emitted — the script silently continues. The tmpDir cleanup just above (lines 34–42) uses a three-branch pattern ending with echo "Warning: ..." >&2. This new block is missing that fallback, making it impossible to distinguish a successful no-op from a failed cleanup in CI logs.

💡 Suggested fix

Add an else branch consistent with the established pattern in this file:

if sudo rm -rf /tmp/awf-*-chroot-home 2>/dev/null; then
  echo "Cleaned up /tmp/awf-*-chroot-home (sudo)"
else
  echo "Warning: failed to clean up /tmp/awf-*-chroot-home" >&2
fi

Note: the success branch will still print even when no directories matched (separate issue already flagged). The else here specifically guards against actual sudo/rm failure.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, add coverage for the chroot-home cleanup path in post.js and clean.sh, and rerun checks after the test updates land.

Generated by 👨‍🍳 PR Sous Chef · 69.1 AIC · ⌖ 0.98 AIC · ⊞ 17.1K ·

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI requested a review from gh-aw-bot June 27, 2026 15:36
@pelikhan pelikhan merged commit f2c5fde into main Jun 27, 2026
40 checks passed
@pelikhan pelikhan deleted the copilot/aw-fix-code-simplifier-failure branch June 27, 2026 17:28
@github-actions

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants