diff --git a/actions/setup/sh/create_gh_aw_tmp_dir.sh b/actions/setup/sh/create_gh_aw_tmp_dir.sh index 1e5d9323963..1639c17eee4 100755 --- a/actions/setup/sh/create_gh_aw_tmp_dir.sh +++ b/actions/setup/sh/create_gh_aw_tmp_dir.sh @@ -34,4 +34,37 @@ mkdir -p /tmp/gh-aw/sandbox/agent/logs # rather than deep inside AWF, surfacing the problem at an earlier step. mkdir -p /tmp/gh-aw/sandbox/firewall/logs mkdir -p /tmp/gh-aw/sandbox/firewall/audit + +# Rootless AWF writes per-run chroot files (including generated /etc/hosts) under +# os.tmpdir(). Pin TMPDIR to a runner-owned subtree so writeConfigs never lands in a +# stale root-owned /tmp/awf-* path on persistent runners. +if [ -d /tmp/gh-aw/awf-tmp ] && [ ! -w /tmp/gh-aw/awf-tmp ]; then + echo "Pre-flight: /tmp/gh-aw/awf-tmp is not writable; reclaiming with sudo" + if command -v sudo >/dev/null 2>&1; then + sudo -n rm -rf /tmp/gh-aw/awf-tmp 2>/dev/null || echo "::warning::sudo rm failed for /tmp/gh-aw/awf-tmp; gh-aw may fail with permission errors. Try: sudo rm -rf /tmp/gh-aw/awf-tmp" + else + echo "::warning::sudo unavailable; cannot reclaim /tmp/gh-aw/awf-tmp; gh-aw may fail with permission errors. Remove /tmp/gh-aw/awf-tmp with admin privileges." + fi +fi +mkdir -p /tmp/gh-aw/awf-tmp + +# Fast pre-flight probe: fail early with a clear message if AWF's temp root can't +# create/write the chroot hosts file it needs during config generation. +AWF_CHROOT_PROBE_DIR="$(mktemp -d /tmp/gh-aw/awf-tmp/chroot-preflight-XXXXXX)" +if ! printf '127.0.0.1 localhost\n' > "${AWF_CHROOT_PROBE_DIR}/hosts"; then + echo "::error::Pre-flight check failed: cannot write to /tmp/gh-aw/awf-tmp." + echo "::error::Check directory ownership and remove stale directories (for example: sudo rm -rf /tmp/gh-aw/awf-tmp)." + exit 1 +fi +rm -rf "${AWF_CHROOT_PROBE_DIR}" + +# Persist TMPDIR for subsequent workflow steps (including Execute GitHub Copilot CLI). +if [ -n "${GITHUB_ENV:-}" ]; then + { + echo "TMPDIR=/tmp/gh-aw/awf-tmp" + echo "TMP=/tmp/gh-aw/awf-tmp" + echo "TEMP=/tmp/gh-aw/awf-tmp" + } >> "${GITHUB_ENV}" +fi + echo "Created /tmp/gh-aw/agent directory for agentic workflow temporary files" diff --git a/actions/setup/sh/create_gh_aw_tmp_dir_test.sh b/actions/setup/sh/create_gh_aw_tmp_dir_test.sh index 089c03fa4e9..930258a467a 100644 --- a/actions/setup/sh/create_gh_aw_tmp_dir_test.sh +++ b/actions/setup/sh/create_gh_aw_tmp_dir_test.sh @@ -46,6 +46,7 @@ bash "${SCRIPT}" >/dev/null 2>&1 assert "creates /tmp/gh-aw/agent" "[ -d /tmp/gh-aw/agent ]" assert "creates /tmp/gh-aw/sandbox/firewall/logs" "[ -d /tmp/gh-aw/sandbox/firewall/logs ]" assert "creates /tmp/gh-aw/sandbox/firewall/audit" "[ -d /tmp/gh-aw/sandbox/firewall/audit ]" +assert "creates /tmp/gh-aw/awf-tmp" "[ -d /tmp/gh-aw/awf-tmp ]" echo "" # ── Test 3: No-op when firewall dir already exists and is writable ─────────── @@ -86,6 +87,32 @@ chmod u+rwx /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true assert "prints Pre-flight reclaim message when subdir is non-writable" "printf '%s' \"${OUTPUT}\" | grep -q 'Pre-flight'" echo "" +# ── Test 6: Exports TMPDIR/TMP/TEMP via GITHUB_ENV for subsequent steps ─────── +echo "Test 6: Exports tmp env vars via GITHUB_ENV" +rm -rf /tmp/gh-aw +GITHUB_ENV_FILE="$(mktemp)" +set +e +GITHUB_ENV="${GITHUB_ENV_FILE}" bash "${SCRIPT}" >/dev/null 2>&1 +EXIT_CODE=$? +set -e +assert "exits 0 when GITHUB_ENV is set" "[ '${EXIT_CODE}' -eq 0 ]" +assert "creates /tmp/gh-aw/awf-tmp when GITHUB_ENV is set" "[ -d /tmp/gh-aw/awf-tmp ]" +assert "exports TMPDIR" "grep -qx 'TMPDIR=/tmp/gh-aw/awf-tmp' '${GITHUB_ENV_FILE}'" +assert "exports TMP" "grep -qx 'TMP=/tmp/gh-aw/awf-tmp' '${GITHUB_ENV_FILE}'" +assert "exports TEMP" "grep -qx 'TEMP=/tmp/gh-aw/awf-tmp' '${GITHUB_ENV_FILE}'" +rm -f "${GITHUB_ENV_FILE}" +echo "" + +# ── Test 7: Succeeds when GITHUB_ENV is unset (local execution) ─────────────── +echo "Test 7: Succeeds when GITHUB_ENV is unset" +rm -rf /tmp/gh-aw +set +e +env -u GITHUB_ENV bash "${SCRIPT}" >/dev/null 2>&1 +EXIT_CODE=$? +set -e +assert "exits 0 when GITHUB_ENV is unset" "[ '${EXIT_CODE}' -eq 0 ]" +echo "" + echo "Tests passed: ${TESTS_PASSED}" echo "Tests failed: ${TESTS_FAILED}"