Compare commits

..
Author SHA1 Message Date
dependabot[bot] 4aa47dc9fb build(deps-dev): bump js-yaml from 4.3.1 to 4.3.2
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.1 to 4.3.2.
- [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.2/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.3.1...4.3.2)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.3.2
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-09-13 05:01:18 +00:00
8 changed files with 31 additions and 177 deletions
-7
View File
@@ -19,13 +19,6 @@ inputs:
description:
'Release tag of the game-ci/cli binary to install and run (e.g. "v0.1.0"). Defaults to the latest release; pin
this for reproducible builds.'
githubToken:
required: false
default: '${{ github.token }}'
description:
'Token used to authenticate the GitHub API call that resolves cliVersion: latest to a concrete release tag.
Defaults to the token GitHub Actions provides for every run automatically - no need to set this unless you
have a reason to override it.'
customImage:
required: false
default: ''
Generated Vendored
+8 -26
View File
@@ -305,28 +305,14 @@ exports.binaryNameFor = binaryNameFor;
* know how to resolve "latest" itself, by design, since which tag it's
* fetched at IS the version it installs.
*/
async function resolveLatestTag(fetchFn = fetch, githubToken) {
async function resolveLatestTag(fetchFn = fetch) {
const headers = { Accept: 'application/vnd.github+json' };
// Actions runners share IPs across many concurrent jobs from unrelated
// repos/orgs, so the unauthenticated rate limit (60 req/hour per IP) gets
// exhausted by traffic this job never generated - hit live via
// game-ci/unity-test-runner#328's consumer, whose six-version matrix failed
// simultaneously with "GitHub API returned 403".
//
// process.env.GITHUB_TOKEN/GH_TOKEN alone does not fix this: GitHub Actions
// does not inject GITHUB_TOKEN into a JS action's process environment
// automatically - a calling workflow has to set it explicitly via env:,
// which essentially no consumer had reason to do before this action started
// making its own API calls. So the env-var-only version of this check was
// unauthenticated for effectively every consumer, not just ones under
// unusual load.
//
// The githubToken *input* (added alongside this) defaults to `${{
// github.token }}`, which GitHub Actions populates on every run with no
// consumer action needed - so it is the primary path, ahead of the env
// vars, which stay as a fallback for the CLI/install.sh path that has no
// Action input to read from.
const token = githubToken || process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
// exhausted by traffic this job never generated. The default GITHUB_TOKEN
// reads public repo data (game-ci/cli's releases) fine regardless of which
// repo the workflow runs in, and lifts the limit to 5000 req/hour.
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
if (token)
headers.Authorization = `Bearer ${token}`;
const response = await fetchFn(`https://api.github.com/repos/${CLI_REPO}/releases/latest`, {
@@ -411,8 +397,8 @@ async function saveToCache(version) {
*
* @param version A release tag (e.g. "v0.1.0"), or "latest".
*/
async function downloadCli(version, githubToken) {
const resolvedVersion = version === 'latest' ? await resolveLatestTag(fetch, githubToken) : version;
async function downloadCli(version) {
const resolvedVersion = version === 'latest' ? await resolveLatestTag() : version;
const cached = await restoreFromCache(resolvedVersion);
if (cached)
return cached;
@@ -519,11 +505,7 @@ const resolve_project_path_1 = __nccwpck_require__(2833);
async function run() {
try {
const cliVersion = core.getInput('cliVersion') || 'latest';
// Defaults to ${{ github.token }}, always populated by Actions - see
// download-cli.ts's resolveLatestTag for why this has to be threaded
// through rather than left to a GITHUB_TOKEN env var.
const githubToken = core.getInput('githubToken') || '';
const cliPath = await (0, download_cli_1.downloadCli)(cliVersion, githubToken);
const cliPath = await (0, download_cli_1.downloadCli)(cliVersion);
const projectPath = (0, resolve_project_path_1.resolveProjectPath)({
input: core.getInput('projectPath'),
existsSync: fs.existsSync,
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -46,7 +46,7 @@
"@vitest/coverage-istanbul": "^4.1.5",
"cross-env": "^7.0.3",
"husky": "9",
"js-yaml": "^4.1.0",
"js-yaml": "^4.3.2",
"lint-staged": "^16.4.0",
"oxfmt": "^0.48.0",
"oxlint": "^1.63.0",
-107
View File
@@ -76,31 +76,6 @@ describe('resolveLatestTag', () => {
}
});
// The githubToken parameter is the action's own `githubToken` input,
// which defaults to `${{ github.token }}` - populated by GitHub Actions on
// every run with no consumer action needed. process.env.GITHUB_TOKEN, by
// contrast, is NOT auto-injected into a JS action's environment - a
// calling workflow has to set it explicitly, which essentially none did.
// Confirmed live via game-ci/unity-test-runner#328: a consumer's six-
// version matrix failed simultaneously with "GitHub API returned 403"
// despite every job having a real, usable token the whole time.
it('sends an Authorization header from the githubToken parameter even when no env var is set', async () => {
const fetchFn = vi.fn(async () => ({
ok: true,
status: 200,
json: async () => ({ tag_name: 'v0.1.15' }),
})) as unknown as typeof fetch;
await resolveLatestTag(fetchFn, 'gha-token-from-input');
expect(fetchFn).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
headers: expect.objectContaining({ Authorization: 'Bearer gha-token-from-input' }),
}),
);
});
it('sends an Authorization header from GITHUB_TOKEN when set, to avoid the unauthenticated rate limit', async () => {
const original = process.env.GITHUB_TOKEN;
process.env.GITHUB_TOKEN = 'test-token-123';
@@ -125,61 +100,6 @@ describe('resolveLatestTag', () => {
}
});
it('falls back to GH_TOKEN when GITHUB_TOKEN is unset', async () => {
const originalGithub = process.env.GITHUB_TOKEN;
const originalGh = process.env.GH_TOKEN;
delete process.env.GITHUB_TOKEN;
process.env.GH_TOKEN = 'gh-token-456';
const fetchFn = vi.fn(async () => ({
ok: true,
status: 200,
json: async () => ({ tag_name: 'v0.1.15' }),
})) as unknown as typeof fetch;
try {
await resolveLatestTag(fetchFn);
expect(fetchFn).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
headers: expect.objectContaining({ Authorization: 'Bearer gh-token-456' }),
}),
);
} finally {
if (originalGithub !== undefined) process.env.GITHUB_TOKEN = originalGithub;
if (originalGh === undefined) delete process.env.GH_TOKEN;
else process.env.GH_TOKEN = originalGh;
}
});
it('prefers the explicit githubToken parameter over GITHUB_TOKEN/GH_TOKEN when both are present', async () => {
const originalGithub = process.env.GITHUB_TOKEN;
const originalGh = process.env.GH_TOKEN;
process.env.GITHUB_TOKEN = 'env-github-token';
process.env.GH_TOKEN = 'env-gh-token';
const fetchFn = vi.fn(async () => ({
ok: true,
status: 200,
json: async () => ({ tag_name: 'v0.1.15' }),
})) as unknown as typeof fetch;
try {
await resolveLatestTag(fetchFn, 'explicit-input-token');
expect(fetchFn).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
headers: expect.objectContaining({ Authorization: 'Bearer explicit-input-token' }),
}),
);
} finally {
if (originalGithub === undefined) delete process.env.GITHUB_TOKEN;
else process.env.GITHUB_TOKEN = originalGithub;
if (originalGh === undefined) delete process.env.GH_TOKEN;
else process.env.GH_TOKEN = originalGh;
}
});
it('throws with a clear message on a non-ok response', async () => {
const fetchFn = vi.fn(async () => ({
ok: false,
@@ -251,33 +171,6 @@ describe('downloadCli', () => {
);
});
// downloadCli is the only caller of resolveLatestTag in production code,
// so this is what actually exercises the wiring index.ts depends on - the
// resolveLatestTag-level test above only proves the function accepts the
// parameter, not that anything passes it one.
it('forwards its githubToken parameter to resolveLatestTag when resolving "latest"', async () => {
globalThis.fetch = vi.fn(async (url: string) => {
if (url.includes('/releases/latest')) {
return { ok: true, status: 200, json: async () => ({ tag_name: 'v0.1.33' }) };
}
return { ok: true, status: 200, text: async () => 'echo mock install.sh' };
}) as unknown as typeof fetch;
vi.mocked(exec.exec).mockImplementation(async (_cmd, _args, options) => {
options?.listeners?.stdout?.(Buffer.from('/tmp/game-ci\n'));
return 0;
});
await downloadCli('latest', 'gha-token-from-input');
expect(globalThis.fetch).toHaveBeenCalledWith(
'https://api.github.com/repos/game-ci/cli/releases/latest',
expect.objectContaining({
headers: expect.objectContaining({ Authorization: 'Bearer gha-token-from-input' }),
}),
);
});
it('resolves "latest" to a concrete tag before fetching install.sh', async () => {
globalThis.fetch = vi.fn(async (url: string) => {
if (url.includes('/releases/latest')) {
+8 -29
View File
@@ -26,31 +26,14 @@ export function binaryNameFor(platform: NodeJS.Platform): string {
* know how to resolve "latest" itself, by design, since which tag it's
* fetched at IS the version it installs.
*/
export async function resolveLatestTag(
fetchFn: typeof fetch = fetch,
githubToken?: string,
): Promise<string> {
export async function resolveLatestTag(fetchFn: typeof fetch = fetch): Promise<string> {
const headers: Record<string, string> = { Accept: 'application/vnd.github+json' };
// Actions runners share IPs across many concurrent jobs from unrelated
// repos/orgs, so the unauthenticated rate limit (60 req/hour per IP) gets
// exhausted by traffic this job never generated - hit live via
// game-ci/unity-test-runner#328's consumer, whose six-version matrix failed
// simultaneously with "GitHub API returned 403".
//
// process.env.GITHUB_TOKEN/GH_TOKEN alone does not fix this: GitHub Actions
// does not inject GITHUB_TOKEN into a JS action's process environment
// automatically - a calling workflow has to set it explicitly via env:,
// which essentially no consumer had reason to do before this action started
// making its own API calls. So the env-var-only version of this check was
// unauthenticated for effectively every consumer, not just ones under
// unusual load.
//
// The githubToken *input* (added alongside this) defaults to `${{
// github.token }}`, which GitHub Actions populates on every run with no
// consumer action needed - so it is the primary path, ahead of the env
// vars, which stay as a fallback for the CLI/install.sh path that has no
// Action input to read from.
const token = githubToken || process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
// exhausted by traffic this job never generated. The default GITHUB_TOKEN
// reads public repo data (game-ci/cli's releases) fine regardless of which
// repo the workflow runs in, and lifts the limit to 5000 req/hour.
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
if (token) headers.Authorization = `Bearer ${token}`;
const response = await fetchFn(`https://api.github.com/repos/${CLI_REPO}/releases/latest`, {
@@ -142,9 +125,8 @@ async function saveToCache(version: string): Promise<void> {
*
* @param version A release tag (e.g. "v0.1.0"), or "latest".
*/
export async function downloadCli(version: string, githubToken?: string): Promise<string> {
const resolvedVersion =
version === 'latest' ? await resolveLatestTag(fetch, githubToken) : version;
export async function downloadCli(version: string): Promise<string> {
const resolvedVersion = version === 'latest' ? await resolveLatestTag() : version;
const cached = await restoreFromCache(resolvedVersion);
if (cached) return cached;
@@ -170,10 +152,7 @@ export async function downloadCli(version: string, githubToken?: string): Promis
`GitHub returned ${scriptResponse.status} for ${installScriptUrl}.`,
);
}
const scriptPath = path.join(
os.tmpdir(),
`game-ci-install-${resolvedVersion.replace(/[^\w.-]/g, '_')}.sh`,
);
const scriptPath = path.join(os.tmpdir(), `game-ci-install-${resolvedVersion.replace(/[^\w.-]/g, '_')}.sh`);
await fs.writeFile(scriptPath, await scriptResponse.text(), { mode: 0o755 });
let stdout = '';
+1 -5
View File
@@ -19,11 +19,7 @@ import { resolveProjectPath } from './resolve-project-path';
export async function run() {
try {
const cliVersion = core.getInput('cliVersion') || 'latest';
// Defaults to ${{ github.token }}, always populated by Actions - see
// download-cli.ts's resolveLatestTag for why this has to be threaded
// through rather than left to a GITHUB_TOKEN env var.
const githubToken = core.getInput('githubToken') || '';
const cliPath = await downloadCli(cliVersion, githubToken);
const cliPath = await downloadCli(cliVersion);
const projectPath = resolveProjectPath({
input: core.getInput('projectPath'),
+12 -1
View File
@@ -2659,6 +2659,17 @@ __metadata:
languageName: node
linkType: hard
"js-yaml@npm:^4.3.2":
version: 4.3.2
resolution: "js-yaml@npm:4.3.2"
dependencies:
argparse: "npm:^2.0.1"
bin:
js-yaml: bin/js-yaml.js
checksum: 10/05c44b9c73e4901d92703b155e76518df64bf01ac62e4c036b47de4b391e19b72e32656e8954d51b436307f08cc9d0c0d4ec617d061cf2f65fffee9f3114bee7
languageName: node
linkType: hard
"jsesc@npm:^3.0.2":
version: 3.1.0
resolution: "jsesc@npm:3.1.0"
@@ -3897,7 +3908,7 @@ __metadata:
"@vitest/coverage-istanbul": "npm:^4.1.5"
cross-env: "npm:^7.0.3"
husky: "npm:9"
js-yaml: "npm:^4.1.0"
js-yaml: "npm:^4.3.2"
lint-staged: "npm:^16.4.0"
oxfmt: "npm:^0.48.0"
oxlint: "npm:^1.63.0"