From 961a84657de0c09d89c0af0350634ca64daa7e3b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Nov 2026 08:28:28 +0000 Subject: [PATCH 1/2] Initial plan From 463d3f87a60cbe4d9a8fedef32e2cdb5275c93c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Nov 2026 08:56:03 +0000 Subject: [PATCH 2/2] test: cover AWF install diagnostics and platform locks Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- actions/setup/sh/install_awf_binary_test.sh | 21 ++++++++ .../awf_installer_integration_test.go | 52 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/actions/setup/sh/install_awf_binary_test.sh b/actions/setup/sh/install_awf_binary_test.sh index 35dda1e1a5f..7b4eb4b5431 100755 --- a/actions/setup/sh/install_awf_binary_test.sh +++ b/actions/setup/sh/install_awf_binary_test.sh @@ -115,6 +115,7 @@ test_curl_retry_all_errors() { local release_version="${7:-v0.28.62}" local attestation_failure="${8:-}" local identity_version="${9:-$release_version}" + local curl_failure_asset="${10:-}" local test_dir local option_index local -a actual_options @@ -149,6 +150,12 @@ while [ "$#" -gt 0 ]; do fi shift done +case "${output:-}" in + */"${AWF_TEST_CURL_FAILURE_ASSET:-__never__}") + echo "simulated curl network failure" >&2 + exit 7 + ;; +esac if [[ "${output}" == *checksums.txt ]]; then printf '%064d awf-linux-x64\n%064d awf-darwin-x64\n%064d awf-bundle.js\n' 0 0 0 > "${output}" elif [[ "${output}" == *release-identity.txt ]]; then @@ -194,6 +201,7 @@ EOF AWF_TEST_MANIFEST_SHA256="$(release_artifact_sha256 github/gh-aw-firewall "$release_version" checksums.txt)" \ CURL_HELP_ALL_OUTPUT="${curl_help_all}" CURL_HELP_OUTPUT="${curl_help}" CURL_HELP_ALL_FAILS="${help_all_fails}" CURL_ARGS_FILE="${test_dir}/curl-args" \ AWF_TEST_ATTESTATION_LOG="${test_dir}/attestations" AWF_TEST_ATTESTATION_FAILURE="$attestation_failure" AWF_TEST_IDENTITY_VERSION="$identity_version" \ + AWF_TEST_CURL_FAILURE_ASSET="$curl_failure_asset" \ AWF_TEST_NODE_VERSION="$node_version" AWF_TEST_OS="$platform" HOME="${test_dir}/home" GITHUB_PATH="${test_dir}/github-path" \ RUNNER_TEMP="$test_dir" PATH="${test_dir}/bin:${PATH}" bash "${SCRIPT_DIR}/install_awf_binary.sh" "$release_version" --rootless >"${test_dir}/output" 2>&1 || installer_exit=$? if [ -n "$attestation_failure" ] || [ "$identity_version" != "$release_version" ]; then @@ -228,6 +236,14 @@ EOF curl_args_files=("${test_dir}"/curl-args.[0-9]*) shopt -u nullglob local expected_downloads=2 + if [ -n "$curl_failure_asset" ]; then + expected_downloads=$((expected_downloads + 1)) + if ! grep -qF "simulated curl network failure" "${test_dir}/output"; then + TEST_FAILURE_REASON="failed curl output was not included in the installer diagnostics" + rm -rf "$test_dir" + return 1 + fi + fi if [ "$release_version" = v0.29.5 ] || [ "$release_version" = v0.29.6 ] || [ "$release_version" = v0.29.7 ]; then expected_downloads=3 if [ "$(wc -l < "${test_dir}/attestations")" -ne 3 ]; then @@ -342,6 +358,11 @@ if test_curl_retry_all_errors '--retry-all-errors' true false '--retry-all-error else fail "mismatched release identity was accepted" "$TEST_FAILURE_REASON" fi +if test_curl_retry_all_errors '--retry-all-errors' true false '--retry-all-errors' v24.0.0 Linux v0.28.62 '' v0.28.62 awf-bundle.js; then + pass "failed download output is included in installer diagnostics before fallback" +else + fail "failed download output was not preserved" "$TEST_FAILURE_REASON" +fi # Test 7: warning emitted when GITHUB_PATH is unset in rootless mode echo "Test 7: warning emitted when GITHUB_PATH is unset in rootless mode..." diff --git a/pkg/workflow/awf_installer_integration_test.go b/pkg/workflow/awf_installer_integration_test.go index 6c78a890b8f..ea241bf7ebe 100644 --- a/pkg/workflow/awf_installer_integration_test.go +++ b/pkg/workflow/awf_installer_integration_test.go @@ -39,6 +39,58 @@ func TestAWFInstallerAuthenticationIsStepLocal(t *testing.T) { } } +func TestAWFInstallerLockUsesBashOnLinuxAndWindows(t *testing.T) { + t.Parallel() + for _, runner := range []string{"ubuntu-latest", "windows-latest"} { + t.Run(runner, func(t *testing.T) { + t.Parallel() + checksum := strings.Repeat("b", 64) + path := filepath.Join(t.TempDir(), "awf-install.md") + content := fmt.Sprintf(`--- +on: workflow_dispatch +strict: false +runs-on: %s +sandbox: + agent: + version: v0.28.62 + checksums-sha256: "%s" +--- +Inspect the repository. +`, runner, checksum) + if err := os.WriteFile(path, []byte(content), 0o600); err != nil { + t.Fatal(err) + } + if err := NewCompiler(WithSkipValidation(true)).CompileWorkflow(path); err != nil { + t.Fatal(err) + } + lock, err := os.ReadFile(strings.TrimSuffix(path, ".md") + ".lock.yml") + if err != nil { + t.Fatal(err) + } + lockText := string(lock) + installStepStart := strings.Index(lockText, " - name: Install AWF binary\n") + if installStepStart < 0 { + t.Fatalf("generated %s lock file lacks the AWF install step:\n%s", runner, lock) + } + installStepEnd := strings.Index(lockText[installStepStart+1:], "\n - ") + installStep := lockText[installStepStart:] + if installStepEnd >= 0 { + installStep = lockText[installStepStart : installStepStart+1+installStepEnd] + } + if !strings.Contains(installStep, `install_awf_binary.sh" v0.28.62 --checksums-sha256 `+checksum) { + t.Errorf("generated %s lock file lacks the pinned installer command:\n%s", runner, installStep) + } + if runner == "windows-latest" { + if !strings.Contains(installStep, "shell: bash") { + t.Errorf("generated Windows install step does not use Bash:\n%s", installStep) + } + } else if strings.Contains(installStep, "shell: bash") { + t.Errorf("generated Linux install step unexpectedly overrides its default shell:\n%s", installStep) + } + }) + } +} + func TestDockerEnclaveHelperInstallerContract(t *testing.T) { t.Parallel() for _, version := range []string{"", "v0.29.5", "0.29.5", "v0.29.6", "0.29.6", "v0.29.7", "0.29.7"} {