Skip to content

proxy-server input is silently ignored (request.agent dropped by @octokit/request v8 native fetch) #2838

Description

@beaufrusetta

Thanks for stopping by to let us know something could be better!

Please provide the following details.

Environment details

  • OS: Linux (self-hosted CI runner, behind a corporate HTTP proxy)
  • Node.js version: 24.x (also reproduces on 22.x)
  • npm version: 10.x
  • release-please version: 17.10.1 (via googleapis/release-please-action@v5), also present on earlier v17 lines

Steps to reproduce

  1. Run release-please on a machine whose only egress to api.github.com is through an HTTP proxy, and set the proxy-server input (action) or --proxy-server-equivalent option (library), e.g. proxy-server: proxy.example.com:912.
  2. Observe that requests do NOT go through the proxy. On a network where direct egress is blocked, the run fails to reach the API (in our case the org IP allow list rejects the runner's raw egress IP); on a network where direct egress is allowed, requests silently bypass the proxy entirely.
  3. Set NODE_USE_ENV_PROXY=1 together with a standard HTTPS_PROXY env var, and requests now go through the proxy correctly, even though proxy-server is unchanged. This is what makes the bug easy to miss: the env var does the work while proxy-server appears to be responsible.

What's happening (root cause)

GitHub.create() builds an HttpsProxyAgent/HttpProxyAgent from the proxy option and passes it as request.agent to Octokit and to the GraphQL client:

// src/github-api.ts
octokit: new Octokit({
  baseUrl: apiUrl,
  auth: options.token,
  request: {
    agent: this.createDefaultAgent(apiUrl, options.proxy),  // <- dropped downstream
    fetch: options.fetch,
  },
}),
// ...and the same request.agent on graphql.defaults({ ... })

But the library depends on @octokit/request ^8.3.1. In @octokit/request v8, the fetch-wrapper calls native fetch and forwards only a fixed set of options:

// @octokit/request@8.4.1 dist-node/index.js (fetch-wrapper)
return fetch(requestOptions.url, {
  method: requestOptions.method,
  body: requestOptions.body,
  headers: requestOptions.headers,
  signal: requestOptions.request?.signal,
  ...(requestOptions.body && { duplex: "half" })
});

request.agent is not among them, so the proxy agent is silently discarded. This is consistent with the @octokit/request v8.0.0 breaking changes, which state: "Replace support for Node.js http(s) Agents with documentation on using fetch dispatchers instead" and "Remove ability to pass custom request options, except method, headers, body, signal, data."

Net effect: the documented proxy-server input (README: "Configure a proxy server in the form of <host>:<port>"; action.yml: "set proxy server when you run this action behind a proxy") is dead code. It is accepted, produces no error, and has no effect. Worse, if a user also sets NODE_USE_ENV_PROXY=1 + HTTPS_PROXY (Node's own env-proxy support), proxying starts working and proxy-server looks like it is doing the job when it is not.

Suggested fix

Follow the same migration Octokit documents for v8: instead of passing request.agent, pass a custom fetch that uses an undici ProxyAgent as its dispatcher, e.g.

import { ProxyAgent } from 'undici';

const dispatcher = proxy ? new ProxyAgent(`http://${proxy.host}:${proxy.port}`) : undefined;
const proxyFetch = dispatcher
  ? (url, opts) => fetch(url, { ...opts, dispatcher })
  : undefined;

new Octokit({ baseUrl: apiUrl, auth: token, request: { fetch: proxyFetch ?? options.fetch } });

(and the equivalent for the GraphQL client). That restores the proxy-server contract on native fetch. Alternatively, if the intent is to rely on Node's env-proxy support, the docs for proxy-server should say so and point at NODE_USE_ENV_PROXY.

I could not find an existing issue for this specific case (#1654 was a related but different graphql-proxy bug predating the octokit v8 bump; #2259 is about HTTP CONNECT tunneling). Happy to open a PR if a fix along these lines is welcome.

Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions