feat: github-api-url (#88)

closes #77

---------

Co-authored-by: Parker Brown <17183625+parkerbxyz@users.noreply.github.com>
This commit is contained in:
Gregor Martynus
2024-01-26 10:51:16 -08:00
committed by GitHub
parent c4fa18d55c
commit 837e2752e0
15 changed files with 107 additions and 55 deletions

View File

@@ -0,0 +1,13 @@
import { test, DEFAULT_ENV } from "./main.js";
// Verify that main works with a custom GitHub API URL passed as `github-api-url` input
await test(
() => {
process.env.INPUT_OWNER = process.env.GITHUB_REPOSITORY_OWNER;
process.env.INPUT_REPOSITORIES = process.env.GITHUB_REPOSITORY;
},
{
...DEFAULT_ENV,
"INPUT_GITHUB-API-URL": "https://github.acme-inc.com/api/v3",
}
);

View File

@@ -2,10 +2,10 @@ import { test } from "./main.js";
// Verify `main` retry when the GitHub API returns a 500 error.
await test((mockPool) => {
process.env.INPUT_OWNER = 'actions'
process.env.INPUT_REPOSITORIES = 'failed-repo';
const owner = process.env.INPUT_OWNER
const repo = process.env.INPUT_REPOSITORIES
process.env.INPUT_OWNER = "actions";
process.env.INPUT_REPOSITORIES = "failed-repo";
const owner = process.env.INPUT_OWNER;
const repo = process.env.INPUT_REPOSITORIES;
const mockInstallationId = "123456";
mockPool
@@ -18,9 +18,9 @@ await test((mockPool) => {
// Intentionally omitting the `authorization` header, since JWT creation is not idempotent.
},
})
.reply(500, 'GitHub API not available')
mockPool
.reply(500, "GitHub API not available");
mockPool
.intercept({
path: `/repos/${owner}/${repo}/installation`,
method: "GET",
@@ -35,5 +35,4 @@ await test((mockPool) => {
{ id: mockInstallationId },
{ headers: { "content-type": "application/json" } }
);
});

View File

@@ -17,8 +17,8 @@ await test((mockPool) => {
// Intentionally omitting the `authorization` header, since JWT creation is not idempotent.
},
})
.reply(500, 'GitHub API not available')
mockPool
.reply(500, "GitHub API not available");
mockPool
.intercept({
path: `/orgs/${process.env.INPUT_OWNER}/installation`,
method: "GET",

View File

@@ -2,14 +2,15 @@
// @ts-check
import { MockAgent, setGlobalDispatcher } from "undici";
export async function test(cb = (_mockPool) => {}) {
// Set required environment variables and inputs
process.env.GITHUB_REPOSITORY_OWNER = "actions";
process.env.GITHUB_REPOSITORY = "actions/create-github-app-token";
export const DEFAULT_ENV = {
GITHUB_REPOSITORY_OWNER: "actions",
GITHUB_REPOSITORY: "actions/create-github-app-token",
// inputs are set as environment variables with the prefix INPUT_
// https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#example-specifying-inputs
process.env["INPUT_APP-ID"] = "123456";
process.env["INPUT_PRIVATE-KEY"] = `-----BEGIN RSA PRIVATE KEY-----
"INPUT_GITHUB-API-URL": "https://api.github.com",
"INPUT_APP-ID": "123456",
// This key is invalidated. Its from https://github.com/octokit/auth-app.js/issues/465#issuecomment-1564998327.
"INPUT_PRIVATE-KEY": `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA280nfuUM9w00Ib9E2rvZJ6Qu3Ua3IqR34ZlK53vn/Iobn2EL
Z9puc5Q/nFBU15NKwHyQNb+OG2hTCkjd1Xi9XPzEOH1r42YQmTGq8YCkUSkk6KZA
5dnhLwN9pFquT9fQgrf4r1D5GJj3rqvj8JDr1sBmunArqY5u4gziSrIohcjLIZV0
@@ -35,27 +36,33 @@ r4J2gqb0xTDfq7gLMNrIXc2QQM4gKbnJp60JQM3p9NmH8huavBZGvSvNzTwXyGG3
so0tiQKBgGQXZaxaXhYUcxYHuCkQ3V4Vsj3ezlM92xXlP32SGFm3KgFhYy9kATxw
Cax1ytZzvlrKLQyQFVK1COs2rHt7W4cJ7op7C8zXfsigXCiejnS664oAuX8sQZID
x3WQZRiXlWejSMUAHuMwXrhGlltF3lw83+xAjnqsVp75kGS6OH61
-----END RSA PRIVATE KEY-----`; // This key is invalidated. Its from https://github.com/octokit/auth-app.js/issues/465#issuecomment-1564998327.
-----END RSA PRIVATE KEY-----`,
};
export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) {
for (const [key, value] of Object.entries(env)) {
process.env[key] = value;
}
// Set up mocking
const baseUrl = new URL(env["INPUT_GITHUB-API-URL"]);
const basePath = baseUrl.pathname === '/' ? '' : baseUrl.pathname;
const mockAgent = new MockAgent();
mockAgent.disableNetConnect();
setGlobalDispatcher(mockAgent);
const mockPool = mockAgent.get("https://api.github.com");
const mockPool = mockAgent.get(baseUrl.origin);
// Calling `auth({ type: "app" })` to obtain a JWT doesnt make network requests, so no need to intercept.
// Mock installation id request
const mockInstallationId = "123456";
const owner = process.env.INPUT_OWNER ?? process.env.GITHUB_REPOSITORY_OWNER;
const owner = env.INPUT_OWNER ?? env.GITHUB_REPOSITORY_OWNER;
const repo = encodeURIComponent(
(process.env.INPUT_REPOSITORIES ?? process.env.GITHUB_REPOSITORY).split(
","
)[0]
(env.INPUT_REPOSITORIES ?? env.GITHUB_REPOSITORY).split(",")[0]
);
mockPool
.intercept({
path: `/repos/${owner}/${repo}/installation`,
path: `${basePath}/repos/${owner}/${repo}/installation`,
method: "GET",
headers: {
accept: "application/vnd.github.v3+json",
@@ -75,7 +82,7 @@ x3WQZRiXlWejSMUAHuMwXrhGlltF3lw83+xAjnqsVp75kGS6OH61
const mockExpiresAt = "2016-07-11T22:14:10Z";
mockPool
.intercept({
path: `/app/installations/${mockInstallationId}/access_tokens`,
path: `${basePath}/app/installations/${mockInstallationId}/access_tokens`,
method: "POST",
headers: {
accept: "application/vnd.github.v3+json",

View File

@@ -4,8 +4,14 @@ import { MockAgent, setGlobalDispatcher } from "undici";
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions
process.env.STATE_token = "secret123";
// inputs are set as environment variables with the prefix INPUT_
// https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#example-specifying-inputs
process.env["INPUT_GITHUB-API-URL"] = "https://api.github.com";
// 1 hour in the future, not expired
process.env.STATE_expiresAt = new Date(Date.now() + 1000 * 60 * 60).toISOString();
process.env.STATE_expiresAt = new Date(
Date.now() + 1000 * 60 * 60
).toISOString();
const mockAgent = new MockAgent();

View File

@@ -4,6 +4,10 @@ import { MockAgent, setGlobalDispatcher } from "undici";
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions
process.env.STATE_token = "secret123";
// inputs are set as environment variables with the prefix INPUT_
// https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#example-specifying-inputs
process.env["INPUT_GITHUB-API-URL"] = "https://api.github.com";
// 1 hour in the future, not expired
process.env.STATE_expiresAt = new Date(Date.now() + 1000 * 60 * 60).toISOString();

View File

@@ -16,6 +16,22 @@ Generated by [AVA](https://avajs.dev).
private_key — 'private_key' is deprecated and will be removed in a future version. Use 'private-key' instead.␊
skip_token_revoke — 'skip_token_revoke' is deprecated and will be removed in a future version. Use 'skip-token-revoke' instead.`
## main-custom-github-api-url.test.js
> stderr
''
> stdout
`owner and repositories set, creating token for repositories "actions/create-github-app-token" owned by "actions"␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=expiresAt::2016-07-11T22:14:10Z`
## main-missing-app-id.test.js
> stderr

Binary file not shown.