Files
T
Yuta Kasai c3c17c79cc fix: use core.getBooleanInput() to retrieve boolean input values (#223)
This PR switches from evaluating values passed to `skip-token-revoke` as
true if they are truthy in JavaScript, to using `getBooleanInput`. This
change ensures that only proper YAML boolean values are recognized,
preventing unintended evaluations to true.
- The definition of `getBooleanInput` is here: definition of
`core#getBooealnInput` is here:
https://github.com/actions/toolkit/blob/930c89072712a3aac52d74b23338f00bb0cfcb24/packages/core/src/core.ts#L188-L208

The documentation states, `"If truthy, the token will not be revoked
when the current job is complete"`, so this change could be considered a
breaking change. This means that if there are users who rely on `truthy`
and expect values like whitespace or `"false"` to be evaluated as true
(though this is likely rare), it would be a breaking change.
- `Boolean(" ")` and `Boolean("false")` are both evaluated as true.

Alternatively, it can simply be considered a fix. How to handle this is
up to the maintainer.

Resolves https://github.com/actions/create-github-app-token/issues/216
2025-04-25 11:59:34 -07:00

124 lines
5.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Base for all `main` tests.
// @ts-check
import { MockAgent, setGlobalDispatcher } from "undici";
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/actions/creating-actions/metadata-syntax-for-github-actions#example-specifying-inputs
"INPUT_GITHUB-API-URL": "https://api.github.com",
"INPUT_SKIP-TOKEN-REVOKE": "false",
"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
cIMz/RUIMe/EAsNeiwzEteHAtf/WpMs+OfF94SIUrDlkPr0H0H3DER8l1HZAvE0e
eD3ZJ6njrF6UHQWDVrekSTB0clpVTTU9TMpe+gs2nnFww9G8As+WsW8xHVjVipJy
AwqBhiR+s7wlcbh2i0NQqt8GL9/jIFTmleiwsQIDAQABAoIBAHNyP8pgl/yyzKzk
/0871wUBMTQ7zji91dGCaFtJM0HrcDK4D/uOOPEv7nE1qDpKPLr5Me1pHUS7+NGw
EAPtlNhgUtew2JfppdIwyi5qeOPADoi7ud6AH8xHsxg+IMwC+JuP8WhzyUHoJj9y
PRi/pX94Mvy9qdE25HqKddjx1mLdaHhxqPkr16/em23uYZqm1lORsCPD3vTlthj7
WiEbBSqmpYvjj8iFP4yFk2N+LvuWgSilRzq1Af3qE7PUp4xhjmcOPs78Sag1T7nl
ww/pgqCegISABHik7j++/5T+UlI5cLsyp/XENU9zAd4kCIczwNKpun2bn+djJdft
ravyX4ECgYEA+k2mHfi1zwKF3wT+cJbf30+uXrJczK2yZ33//4RKnhBaq7nSbQAI
nhWz2JESBK0TEo0+L7yYYq3HnT9vcES5R1NxzruH9wXgxssSx3JUj6w1raXYPh3B
+1XpYQsa6/bo2LmBELEx47F8FQbNgD5dmTJ4jBrf6MV4rRh9h6Bs7UkCgYEA4M3K
eAw52c2MNMIxH/LxdOQtEBq5GMu3AQC8I64DSSRrAoiypfEgyTV6S4gWJ5TKgYfD
zclnOVJF+tITe3neO9wHoZp8iCjCnoijcT6p2cJ4IaW68LEHPOokWBk0EpLjF4p2
7sFi9+lUpXYXfCN7aMJ77QpGzB7dNsBf0KUxMCkCgYEAjw/mjGbk82bLwUaHby6s
0mQmk7V6WPpGZ+Sadx7TzzglutVAslA8nK5m1rdEBywtJINaMcqnhm8xEm15cj+1
blEBUVnaQpQ3fyf+mcR9FIknPRL3X7l+b/sQowjH4GqFd6m/XR0KGMwO0a3Lsyry
MGeqgtmxdMe5S6YdyXEmERECgYAgQsgklDSVIh9Vzux31kh6auhgoEUh3tJDbZSS
Vj2YeIZ21aE1mTYISglj34K2aW7qSc56sMWEf18VkKJFHQccdgYOVfo7HAZZ8+fo
r4J2gqb0xTDfq7gLMNrIXc2QQM4gKbnJp60JQM3p9NmH8huavBZGvSvNzTwXyGG3
so0tiQKBgGQXZaxaXhYUcxYHuCkQ3V4Vsj3ezlM92xXlP32SGFm3KgFhYy9kATxw
Cax1ytZzvlrKLQyQFVK1COs2rHt7W4cJ7op7C8zXfsigXCiejnS664oAuX8sQZID
x3WQZRiXlWejSMUAHuMwXrhGlltF3lw83+xAjnqsVp75kGS6OH61
-----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({ enableCallHistory: true });
mockAgent.disableNetConnect();
setGlobalDispatcher(mockAgent);
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 and app slug request
const mockInstallationId = "123456";
const mockAppSlug = "github-actions";
const owner = env.INPUT_OWNER ?? env.GITHUB_REPOSITORY_OWNER;
const currentRepoName = env.GITHUB_REPOSITORY.split("/")[1];
const repo = encodeURIComponent(
(env.INPUT_REPOSITORIES ?? currentRepoName).split(",")[0],
);
mockPool
.intercept({
path: `${basePath}/repos/${owner}/${repo}/installation`,
method: "GET",
headers: {
accept: "application/vnd.github.v3+json",
"user-agent": "actions/create-github-app-token",
// Intentionally omitting the `authorization` header, since JWT creation is not idempotent.
},
})
.reply(
200,
{ id: mockInstallationId, app_slug: mockAppSlug },
{ headers: { "content-type": "application/json" } },
);
// Mock installation access token request
const mockInstallationAccessToken =
"ghs_16C7e42F292c6912E7710c838347Ae178B4a"; // This token is invalidated. Its from https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app.
const mockExpiresAt = "2016-07-11T22:14:10Z";
mockPool
.intercept({
path: `${basePath}/app/installations/${mockInstallationId}/access_tokens`,
method: "POST",
headers: {
accept: "application/vnd.github.v3+json",
"user-agent": "actions/create-github-app-token",
// Note: Intentionally omitting the `authorization` header, since JWT creation is not idempotent.
},
})
.reply(
201,
{ token: mockInstallationAccessToken, expires_at: mockExpiresAt },
{ headers: { "content-type": "application/json" } },
);
// Run the callback
cb(mockPool);
// Run the main script
const { default: promise } = await import("../main.js");
await promise;
console.log("--- REQUESTS ---");
const calls = mockAgent
.getCallHistory()
.calls()
.map((call) => {
const route = `${call.method} ${call.path}`;
if (call.method === "GET") return route;
return `${route}\n${call.body}`;
});
console.log(calls.join("\n"));
}