Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: introduce dedicated option for GitHub API endpoint #829

Merged
merged 3 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,20 @@ When using the _GITHUB_TOKEN_, the **minimum required permissions** are:

### Environment variables

| Variable | Description |
| -------------------------------------------- | --------------------------------------------------------- |
| `GH_TOKEN` or `GITHUB_TOKEN` | **Required.** The token used to authenticate with GitHub. |
| `GITHUB_API_URL` or `GH_URL` or `GITHUB_URL` | The GitHub Enterprise endpoint. |
| `GH_PREFIX` or `GITHUB_PREFIX` | The GitHub Enterprise API prefix. |
| Variable | Description |
| ------------------------------ | ------------------------------------------------------------------- |
| `GITHUB_TOKEN` or `GH_TOKEN` | **Required.** The token used to authenticate with GitHub. |
| `GITHUB_URL` or `GH_URL` | The GitHub server endpoint. |
| `GITHUB_PREFIX` or `GH_PREFIX` | The GitHub API prefix, relative to `GITHUB_URL`. |
| `GITHUB_API_URL` | The GitHub API endpoint. Note that this overwrites `GITHUB_PREFIX`. |
Comment on lines +74 to +79
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Independent of this change it might also be worth to deprecate some of these variables to align with what is currently supported: https://docs.github.com/en/actions/learn-github-actions/variables.


### Options

| Option | Description | Default |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `githubUrl` | The GitHub Enterprise endpoint. | `GH_URL` or `GITHUB_URL` environment variable. |
| `githubApiPathPrefix` | The GitHub Enterprise API prefix. | `GH_PREFIX` or `GITHUB_PREFIX` environment variable. |
| `githubUrl` | The GitHub server endpoint. | `GH_URL` or `GITHUB_URL` environment variable. |
| `githubApiPathPrefix` | The GitHub API prefix, relative to `githubUrl`. | `GH_PREFIX` or `GITHUB_PREFIX` environment variable. |
| `githubApiUrl` | The GitHub API endpoint. Note that this overwrites `githubApiPathPrefix`. | `GITHUB_API_URL` environment variable. |
| `proxy` | The proxy to use to access the GitHub API. Set to `false` to disable usage of proxy. See [proxy](#proxy). | `HTTP_PROXY` environment variable. |
| `assets` | An array of files to upload to the release. See [assets](#assets). | - |
| `successComment` | The comment to add to each issue and pull request resolved by the release. Set to `false` to disable commenting on issues and pull requests. See [successComment](#successcomment). | `:tada: This issue has been resolved in version ${nextRelease.version} :tada:\n\nThe release is available on [GitHub release](<github_release_url>)` |
Expand Down
7 changes: 3 additions & 4 deletions lib/add-channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@ export default async function addChannel(pluginConfig, context, { Octokit }) {
nextRelease: { name, gitTag, notes },
logger,
} = context;
const { githubToken, githubUrl, githubApiPathPrefix, proxy } = resolveConfig(
pluginConfig,
context,
);
const { githubToken, githubUrl, githubApiPathPrefix, githubApiUrl, proxy } =
resolveConfig(pluginConfig, context);
const { owner, repo } = parseGithubUrl(repositoryUrl);
const octokit = new Octokit(
toOctokitOptions({
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
}),
);
Expand Down
9 changes: 8 additions & 1 deletion lib/fail.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default async function fail(pluginConfig, context, { Octokit }) {
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
failComment,
failTitle,
Expand All @@ -32,7 +33,13 @@ export default async function fail(pluginConfig, context, { Octokit }) {
logger.log("Skip issue creation.");
} else {
const octokit = new Octokit(
toOctokitOptions({ githubToken, githubUrl, githubApiPathPrefix, proxy }),
toOctokitOptions({
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
}),
);
// In case the repo changed name, get the new `repo`/`owner` as the search API will not follow redirects
const { data: repoData } = await octokit.request(
Expand Down
10 changes: 6 additions & 4 deletions lib/octokit.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@ export const SemanticReleaseOctokit = Octokit.plugin(
/* c8 ignore stop */

/**
* @param {{githubToken: string, proxy: any} | {githubUrl: string, githubApiPathPrefix: string, githubToken: string, proxy: any}} options
* @param {{githubToken: string, proxy: any} | {githubUrl: string, githubApiPathPrefix: string, githubApiUrl: string,githubToken: string, proxy: any}} options
* @returns {{ auth: string, baseUrl?: string, request: { agent?: any } }}
*/
export function toOctokitOptions(options) {
const baseUrl =
"githubUrl" in options && options.githubUrl
? urljoin(options.githubUrl, options.githubApiPathPrefix)
: undefined;
"githubApiUrl" in options && options.githubApiUrl
? options.githubApiUrl
: "githubUrl" in options && options.githubUrl
? urljoin(options.githubUrl, options.githubApiPathPrefix)
: undefined;

const agent = options.proxy
? baseUrl && new URL(baseUrl).protocol.replace(":", "") === "http"
Expand Down
2 changes: 2 additions & 0 deletions lib/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default async function publish(pluginConfig, context, { Octokit }) {
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
assets,
draftRelease,
Expand All @@ -39,6 +40,7 @@ export default async function publish(pluginConfig, context, { Octokit }) {
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
}),
);
Expand Down
4 changes: 3 additions & 1 deletion lib/resolve-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { isNil, castArray } from "lodash-es";
export default function resolveConfig(
{
githubUrl,
githubApiUrl,
githubApiPathPrefix,
proxy,
assets,
Expand All @@ -22,9 +23,10 @@ export default function resolveConfig(
) {
return {
githubToken: env.GH_TOKEN || env.GITHUB_TOKEN,
githubUrl: githubUrl || env.GITHUB_API_URL || env.GH_URL || env.GITHUB_URL,
githubUrl: githubUrl || env.GH_URL || env.GITHUB_URL,
githubApiPathPrefix:
githubApiPathPrefix || env.GH_PREFIX || env.GITHUB_PREFIX || "",
githubApiUrl: githubApiUrl || env.GITHUB_API_URL,
proxy: isNil(proxy) ? env.http_proxy || env.HTTP_PROXY || false : proxy,
assets: assets ? castArray(assets) : assets,
successComment,
Expand Down
9 changes: 8 additions & 1 deletion lib/success.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default async function success(pluginConfig, context, { Octokit }) {
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
successComment,
failComment,
Expand All @@ -36,7 +37,13 @@ export default async function success(pluginConfig, context, { Octokit }) {
} = resolveConfig(pluginConfig, context);

const octokit = new Octokit(
toOctokitOptions({ githubToken, githubUrl, githubApiPathPrefix, proxy }),
toOctokitOptions({
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
}),
);

// In case the repo changed name, get the new `repo`/`owner` as the search API will not follow redirects
Expand Down
22 changes: 18 additions & 4 deletions lib/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,14 @@ export default async function verify(pluginConfig, context, { Octokit }) {
options: { repositoryUrl },
logger,
} = context;
const { githubToken, githubUrl, githubApiPathPrefix, proxy, ...options } =
resolveConfig(pluginConfig, context);
const {
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
...options
} = resolveConfig(pluginConfig, context);

const errors = Object.entries({ ...options, proxy }).reduce(
(errors, [option, value]) =>
Expand All @@ -70,7 +76,9 @@ export default async function verify(pluginConfig, context, { Octokit }) {
[],
);

if (githubUrl) {
if (githubApiUrl) {
logger.log("Verify GitHub authentication (%s)", githubApiUrl);
} else if (githubUrl) {
logger.log(
"Verify GitHub authentication (%s)",
urlJoin(githubUrl, githubApiPathPrefix),
Expand All @@ -87,7 +95,13 @@ export default async function verify(pluginConfig, context, { Octokit }) {
!errors.find(({ code }) => code === "EINVALIDPROXY")
) {
const octokit = new Octokit(
toOctokitOptions({ githubToken, githubUrl, githubApiPathPrefix, proxy }),
toOctokitOptions({
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
}),
);

// https://github.com/semantic-release/github/issues/182
Expand Down
75 changes: 74 additions & 1 deletion test/verify.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ test("Verify package, token and repository with environment variables", async (t
]);
});

test("Verify package, token and repository access with alternative environment varialbes", async (t) => {
test("Verify package, token and repository access with alternative environment variables", async (t) => {
const owner = "test_user";
const repo = "test_repo";
const env = {
Expand Down Expand Up @@ -299,6 +299,79 @@ test("Verify package, token and repository access with alternative environment v
t.true(fetch.done());
});

test("Verify package, token and repository access with custom API URL", async (t) => {
const owner = "test_user";
const repo = "test_repo";
const env = { GH_TOKEN: "github_token" };
const githubUrl = "https://othertesturl.com:9090";
const githubApiUrl = "https://api.othertesturl.com:9090";

const fetch = fetchMock
.sandbox()
.getOnce(`https://api.othertesturl.com:9090/repos/${owner}/${repo}`, {
permissions: { push: true },
});

await t.notThrowsAsync(
verify(
{ githubUrl, githubApiUrl },
{
env,
options: { repositoryUrl: `github:${owner}/${repo}` },
logger: t.context.logger,
},
{
Octokit: TestOctokit.defaults((options) => ({
...options,
request: { ...options.request, fetch },
})),
},
),
);

t.true(fetch.done());
t.deepEqual(t.context.log.args[0], [
"Verify GitHub authentication (%s)",
"https://api.othertesturl.com:9090",
]);
});

test("Verify package, token and repository access with API URL in environment variable", async (t) => {
const owner = "test_user";
const repo = "test_repo";
const env = {
GITHUB_URL: "https://othertesturl.com:443",
GITHUB_API_URL: "https://api.othertesturl.com:443",
GITHUB_TOKEN: "github_token",
};

const fetch = fetchMock
.sandbox()
.getOnce(`https://api.othertesturl.com:443/repos/${owner}/${repo}`, {
permissions: { push: true },
});

await t.notThrowsAsync(
verify(
{},
{
env,
options: {
repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`,
},
logger: t.context.logger,
},
{
Octokit: TestOctokit.defaults((options) => ({
...options,
request: { ...options.request, fetch },
})),
},
),
);
t.true(fetch.done());
});

test('Verify "proxy" is a String', async (t) => {
const owner = "test_user";
const repo = "test_repo";
Expand Down