From 3f97bbef1f33e7bc2bb59392a1bc76781d5ee96e Mon Sep 17 00:00:00 2001 From: reginaldalfret Date: Mon, 26 Oct 2026 16:25:12 +0530 Subject: [PATCH] fix: handle non-string variables in setup-vars and update eslint n rules (#4174) Signed-off-by: reginaldalfret --- .eslintrc.json | 11 +++++--- .github/scripts/setup-vars.js | 17 +++++++----- .github/scripts/setup-vars.test.js | 42 +++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 44510807abe..1d8c1fe9a6a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,11 +5,16 @@ "mocha": true }, "rules": { - "node/no-missing-import": ["off"], - "node/no-missing-require": ["off"], + "node/no-missing-import": ["off"], + "node/no-missing-require": ["off"], "node/no-unpublished-import": ["off"], "node/no-unpublished-require": ["off"], - "node/no-unsupported-features/es-syntax": ["off"] + "node/no-unsupported-features/es-syntax": ["off"], + "n/no-missing-import": ["off"], + "n/no-missing-require": ["off"], + "n/no-unpublished-import": ["off"], + "n/no-unpublished-require": ["off"], + "n/no-unsupported-features/es-syntax": ["off"] }, "parserOptions": { "ecmaVersion": 2020, diff --git a/.github/scripts/setup-vars.js b/.github/scripts/setup-vars.js index 54202abcca4..daca6c990f5 100644 --- a/.github/scripts/setup-vars.js +++ b/.github/scripts/setup-vars.js @@ -46,13 +46,15 @@ export default function setupVars({projectId, core, setup, serviceAccount, idTok console.log(` ${key}: ${setup.secrets[key]}`); } - // Set global secret for the Service Account identity token + // Set global secret for the Service Account identity token if provided // Use in place of 'gcloud auth print-identity-token' or auth.getIdTokenClient // usage: curl -H 'Bearer: $ID_TOKEN' https:// - core.exportVariable('ID_TOKEN', idToken) - core.setSecret(idToken) - // For logging, show the source of the ID_TOKEN - console.log(` ID_TOKEN: steps.auth.outputs.id_token (from GitHub Action)`); + if (idToken) { + core.exportVariable('ID_TOKEN', idToken); + core.setSecret(idToken); + // For logging, show the source of the ID_TOKEN + console.log(` ID_TOKEN: steps.auth.outputs.id_token (from GitHub Action)`); + } // Return env and secrets to use for further steps. return { @@ -65,9 +67,12 @@ export default function setupVars({projectId, core, setup, serviceAccount, idTok } export function substituteVars(value, env) { + if (value === null || value === undefined || typeof value !== 'string') { + return value; + } for (const key in env) { let re = new RegExp(`\\$(${key}\\b|\\{\\s*${key}\\s*\\})`, 'g'); - value = value.replaceAll(re, env[key]); + value = value.replaceAll(re, String(env[key])); } return value; } diff --git a/.github/scripts/setup-vars.test.js b/.github/scripts/setup-vars.test.js index e1f4b47b907..565972f3ae4 100644 --- a/.github/scripts/setup-vars.test.js +++ b/.github/scripts/setup-vars.test.js @@ -14,7 +14,7 @@ limitations under the License. */ -import {deepStrictEqual} from 'assert'; +import {deepStrictEqual, strictEqual} from 'assert'; import setupVars from './setup-vars.js'; import {substituteVars, uniqueId} from './setup-vars.js'; @@ -57,6 +57,13 @@ describe('setupVars', () => { deepStrictEqual(vars.env, expected); }); + it('should support non-string variables without throwing', () => { + const setup = {env: {PORT: 8080, ENABLED: true, URL: 'http://localhost:$PORT'}}; + const vars = setupVars({projectId, core, setup, serviceAccount}, 'run-id'); + const expected = {...autovars, PORT: 8080, ENABLED: true, URL: 'http://localhost:8080'}; + deepStrictEqual(vars.env, expected); + }); + it('should override automatic variables', () => { const setup = {env: {PROJECT_ID: 'custom-value', SERVICE_ACCOUNT: 'baz@foo.com'}}; const vars = setupVars({projectId, core, setup, serviceAccount}, 'run-id'); @@ -82,6 +89,32 @@ describe('setupVars', () => { }); }); + describe('idToken handling', () => { + it('should export and setSecret ID_TOKEN when idToken is provided', () => { + const exported = {}; + const secrets = []; + const testCore = { + exportVariable: (k, v) => { exported[k] = v; }, + setSecret: (s) => { secrets.push(s); }, + }; + setupVars({projectId, core: testCore, setup: {}, serviceAccount, idToken: 'test-token-123'}, 'run-id'); + strictEqual(exported['ID_TOKEN'], 'test-token-123'); + deepStrictEqual(secrets, ['test-token-123']); + }); + + it('should not export or setSecret ID_TOKEN when idToken is missing', () => { + const exported = {}; + const secrets = []; + const testCore = { + exportVariable: (k, v) => { exported[k] = v; }, + setSecret: (s) => { secrets.push(s); }, + }; + setupVars({projectId, core: testCore, setup: {}, serviceAccount}, 'run-id'); + strictEqual(exported['ID_TOKEN'], undefined); + deepStrictEqual(secrets, []); + }); + }); + describe('secrets', () => { it('zero secrets', () => { const setup = {secrets: {}}; @@ -146,6 +179,13 @@ describe('substituteVars', () => { const expected = '$Ab'; deepStrictEqual(got, expected); }); + + it('should safely return non-string inputs', () => { + strictEqual(substituteVars(8080, {A: 'x'}), 8080); + strictEqual(substituteVars(true, {A: 'x'}), true); + strictEqual(substituteVars(null, {A: 'x'}), null); + strictEqual(substituteVars(undefined, {A: 'x'}), undefined); + }); }); describe('uniqueId', () => {