Skip to content

Fix dependency fetching behind an HTTP proxy#2956

Merged
plajjan merged 4 commits into
mainfrom
fix-proxy-dependency-fetch
Jun 20, 2026
Merged

Fix dependency fetching behind an HTTP proxy#2956
plajjan merged 4 commits into
mainfrom
fix-proxy-dependency-fetch

Conversation

@plajjan

@plajjan plajjan commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

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.

Kristian Larsson and others added 3 commits June 20, 2026 09:17
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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment thread .github/workflows/test.yml
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.
@plajjan plajjan force-pushed the fix-proxy-dependency-fetch branch from 0792d23 to 81c9a3e Compare June 20, 2026 08:26
@plajjan plajjan enabled auto-merge June 20, 2026 08:28
@plajjan plajjan merged commit c6775cf into main Jun 20, 2026
50 of 51 checks passed
@plajjan plajjan deleted the fix-proxy-dependency-fetch branch June 20, 2026 09:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants