Fix dependency fetching behind an HTTP proxy#2956
Merged
Merged
Conversation
When a dependency download fails, replace the raw http-client request-record dump with a clean message: the failure cause, the proxy variable that applies to the request (https_proxy for https), the proxy environment acton saw, and a hint for the common trap where the proxy vars never reach the build (sudo/root, make, CI). With --verbose, print the proxy environment up front. Read the environment via getEnvironment -- the same source http-client's proxyEnvironment consults -- so the diagnostic agrees with the proxy actually selected, including on binaries where getEnvironment and getenv disagree.
Bring up two containers via docker compose: an Oracle Linux 9 box with acton installed from the release tarball, attached only to an internal network with no direct egress, and a tinyproxy that is its sole route out. `acton fetch` must pull a remote dependency through the proxy; with no direct egress, success means acton honoured http(s)_proxy. Run it with `make test-proxy`. A CI job runs it on amd64 and arm64 (host runners, so Docker is available) and gates releases. This reproduces the x86_64 -no-pie environ/getEnvironment bug, where the proxy vars never reach acton's HTTP client; arm64 is the unaffected control.
acton and lsp-server-acton are linked as -no-pie executables by zig cc (to target an older glibc). Under that link lld emits a copy relocation for glibc's `environ` but does not redirect the `__environ` alias to it, so __libc_start_main populates __environ (getenv/lookupEnv keep working) while the executable's `environ` copy -- which GHC's RTS reads for getEnvironment -- stays NULL. getEnvironment then returns [], so e.g. http-client's proxyEnvironment never sees HTTP(S)_PROXY and dependency fetches ignore the proxy. Link a small C shim (cbits/environ_fix.c) into both executables: it defines `environ` in the executable (so no copy relocation is generated) and points it at glibc's live __environ in a startup constructor. Linux only.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 10a36f9994
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Add test-proxy to the needs of build-container-image, update-apt-repo, update-apt-tip-repo, and update-homebrew so every job that publishes an artifact (GHCR images, APT, Homebrew) waits on the proxy regression test, alongside release and pre-release-tip.
0792d23 to
81c9a3e
Compare
This was referenced Jun 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Acton could not fetch dependencies from GitHub when run behind an HTTP proxy, even with http_proxy and https_proxy exported. The proxy, the network, and the user's configuration were all fine. The real cause is a link-time issue: the Linux compiler binary is linked with zig cc as a no-pie executable to target an older glibc, and under that link GHC's getEnvironment returns an empty environment. This is an lld copy-relocation difference for the glibc environ symbol and its __environ alias. libc's getenv still works, so lookupEnv and things like HOME resolve, but http-client's proxyEnvironment reads the whole environment via getEnvironment, so it never saw the proxy variables and always connected directly. On a proxy-only network that fails and nothing is fetched. This only manifests on x86_64; aarch64 binaries are unaffected, which is part of why it was so hard to pin down. In the field this looked baffling because curl on the same host and shell reached GitHub through the proxy while acton did not.
There are three commits. The first improves the diagnostics. When a dependency download fails, acton now prints the proxy variable that applies to the request, the proxy environment it actually saw, and an actionable hint, instead of dumping the raw http-client request record. It reads the environment through getEnvironment, the same source proxyEnvironment uses, so the diagnostic agrees with the proxy that was actually selected rather than with getenv.
The second commit adds a reproduction and regression test, runnable with make test-proxy. It uses docker compose to bring up an Oracle Linux 9 container with acton installed from the release tarball, attached only to an internal network with no direct egress, plus a tinyproxy that is its only route out. acton fetch must then pull a remote dependency through the proxy, and because there is no direct egress a successful fetch is only possible if acton honoured the proxy variables. A control step proves the proxy path itself works first, so a failure is acton's and not the test infrastructure. A CI job runs this on both amd64 and arm64 host runners and gates the release and pre-release jobs. Before the fix the amd64 job fails, reproducing the report, while arm64 passes as the unaffected control.
The third commit is the fix itself, repairing getEnvironment under the zig cc link by defining environ in the executable, which removes the copy relocation, and pointing it at glibc's live __environ in a startup constructor. It is gated to Linux.