Skip to content

Commit 1603e2f

Browse files
committed
feat: support the no_proxy environment variable
Closes #563 BREAKING CHANGE: The `no_proxy` and `NO_PROXY` environment variables are now respected when obtaining proxy configuration from the environment, bypassing the proxy when they match the GitHub host. This does not apply when [`proxy`](https://github.com/semantic-release/github#proxy) is explicitly provided in the plugin configuration.
1 parent 5d1f65e commit 1603e2f

File tree

3 files changed

+88
-18
lines changed

3 files changed

+88
-18
lines changed

lib/resolve-config.js

+23-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const {isNil, castArray} = require('lodash');
2+
const resolveProxy = require('./resolve-proxy');
23

34
module.exports = (
45
{
@@ -15,21 +16,25 @@ module.exports = (
1516
addReleases,
1617
},
1718
{env}
18-
) => ({
19-
githubToken: env.GH_TOKEN || env.GITHUB_TOKEN,
20-
githubUrl: githubUrl || env.GITHUB_API_URL || env.GH_URL || env.GITHUB_URL,
21-
githubApiPathPrefix: githubApiPathPrefix || env.GH_PREFIX || env.GITHUB_PREFIX || '',
22-
proxy: isNil(proxy) ? env.http_proxy || env.HTTP_PROXY || false : proxy,
23-
assets: assets ? castArray(assets) : assets,
24-
successComment,
25-
failTitle: isNil(failTitle) ? 'The automated release is failing 🚨' : failTitle,
26-
failComment,
27-
labels: isNil(labels) ? ['semantic-release'] : labels === false ? false : castArray(labels),
28-
assignees: assignees ? castArray(assignees) : assignees,
29-
releasedLabels: isNil(releasedLabels)
30-
? [`released<%= nextRelease.channel ? \` on @\${nextRelease.channel}\` : "" %>`]
31-
: releasedLabels === false
32-
? false
33-
: castArray(releasedLabels),
34-
addReleases: isNil(addReleases) ? false : addReleases,
35-
});
19+
) => {
20+
githubUrl ||= env.GITHUB_API_URL || env.GH_URL || env.GITHUB_URL;
21+
22+
return {
23+
githubToken: env.GH_TOKEN || env.GITHUB_TOKEN,
24+
githubUrl,
25+
githubApiPathPrefix: githubApiPathPrefix || env.GH_PREFIX || env.GITHUB_PREFIX || '',
26+
proxy: isNil(proxy) ? resolveProxy(githubUrl, env) : proxy,
27+
assets: assets ? castArray(assets) : assets,
28+
successComment,
29+
failTitle: isNil(failTitle) ? 'The automated release is failing 🚨' : failTitle,
30+
failComment,
31+
labels: isNil(labels) ? ['semantic-release'] : labels === false ? false : castArray(labels),
32+
assignees: assignees ? castArray(assignees) : assignees,
33+
releasedLabels: isNil(releasedLabels)
34+
? [`released<%= nextRelease.channel ? \` on @\${nextRelease.channel}\` : "" %>`]
35+
: releasedLabels === false
36+
? false
37+
: castArray(releasedLabels),
38+
addReleases: isNil(addReleases) ? false : addReleases,
39+
};
40+
};

lib/resolve-proxy.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
module.exports = (githubUrl, env) => {
2+
githubUrl ||= 'https://github.com';
3+
const proxy = env.http_proxy || env.HTTP_PROXY || false;
4+
const noProxy = env.no_proxy || env.NO_PROXY;
5+
6+
if (proxy && noProxy) {
7+
const {hostname} = new URL(githubUrl);
8+
for (let noProxyHost of noProxy.split(',')) {
9+
if (noProxyHost === '*') {
10+
return false;
11+
}
12+
13+
if (noProxyHost.startsWith('.')) {
14+
noProxyHost = noProxyHost.slice(1);
15+
}
16+
17+
if (hostname === noProxyHost || hostname.endsWith('.' + noProxyHost)) {
18+
return false;
19+
}
20+
}
21+
}
22+
23+
return proxy;
24+
};

test/resolve-proxy.test.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const test = require('ava');
2+
const resolveProxy = require('../lib/resolve-proxy');
3+
4+
test('Resolve proxy with no proxy configuration', (t) => {
5+
t.is(resolveProxy(undefined, {}), false);
6+
});
7+
8+
test('Resolve proxy with no exclusions', (t) => {
9+
t.is(resolveProxy(undefined, {http_proxy: 'proxy.example.com'}), 'proxy.example.com');
10+
});
11+
12+
test('Resolve proxy with no matching exclusion', (t) => {
13+
t.is(
14+
resolveProxy(undefined, {http_proxy: 'proxy.example.com', no_proxy: 'notgithub.com,.example.org,example.net'}),
15+
'proxy.example.com'
16+
);
17+
});
18+
19+
test('Resolve proxy with matching exclusion', (t) => {
20+
t.is(resolveProxy(undefined, {http_proxy: 'proxy.example.com', no_proxy: 'github.com'}), false);
21+
});
22+
23+
test('Resolve proxy with matching exclusion (leading .)', (t) => {
24+
t.is(resolveProxy(undefined, {http_proxy: 'proxy.example.com', no_proxy: '.github.com'}), false);
25+
});
26+
27+
test('Resolve proxy with global exclusion', (t) => {
28+
t.is(resolveProxy(undefined, {http_proxy: 'proxy.example.com', no_proxy: '*'}), false);
29+
});
30+
31+
test('Resolve proxy with matching GitHub Enterprise exclusion', (t) => {
32+
t.is(resolveProxy('https://github.example.com', {http_proxy: 'proxy.example.com', no_proxy: 'example.com'}), false);
33+
});
34+
35+
test('Resolve proxy with uppercase environment variables', (t) => {
36+
t.is(resolveProxy(undefined, {HTTP_PROXY: 'proxy.example.com', NO_PROXY: 'github.com'}), false);
37+
t.is(
38+
resolveProxy(undefined, {HTTP_PROXY: 'proxy.example.com', NO_PROXY: 'subdomain.github.com'}),
39+
'proxy.example.com'
40+
);
41+
});

0 commit comments

Comments
 (0)