const { test } = require('node:test'); const assert = require('node:assert/strict'); const { spawnSync } = require('node:child_process'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const ROOT = path.join(__dirname, '..'); const SCRIPT = path.join(ROOT, 'scripts', 'publish-deb.sh'); const TOKEN = 'deb-token-that-must-not-appear-in-output'; function runScenario({ token = '' } = {}) { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-publish-deb-test-')); try { const home = path.join(dir, 'home'); const bin = path.join(dir, 'bin'); const deb = path.join(dir, 'stoke_2.0.0_all.deb'); fs.mkdirSync(home); fs.mkdirSync(bin); fs.writeFileSync(deb, 'package'); fs.writeFileSync(path.join(bin, 'curl'), '#!/usr/bin/env bash\nprintf 201\n'); fs.chmodSync(path.join(bin, 'curl'), 0o755); return spawnSync('bash', [SCRIPT, deb], { encoding: 'utf8', env: { HOME: home, PATH: `${bin}:${process.env.PATH}`, STOKE_CONFIG_FILE: path.join(dir, 'missing-config.json'), STOKE_TOKEN: token, }, }); } finally { fs.rmSync(dir, { recursive: true, force: true }); } } test('empty token identifies the CI secret before offering the local remedy', () => { const result = runScenario(); assert.equal(result.status, 1); assert.equal(result.stdout, ''); assert.match(result.stderr, /^error: no token\./); assert.match(result.stderr, /STOKE_TOKEN/); assert.match(result.stderr, /RELEASE_TOKEN/); assert.match(result.stderr, /empty value.*secret/is); assert.ok(result.stderr.indexOf('RELEASE_TOKEN') < result.stderr.indexOf('stoke auth login')); }); test('non-empty environment token passes the guard without exposing the token', () => { const result = runScenario({ token: TOKEN }); assert.equal(result.status, 0, result.stderr); assert.match(result.stdout, /Published\./); assert.doesNotMatch(result.stdout, new RegExp(TOKEN)); assert.doesNotMatch(result.stderr, new RegExp(TOKEN)); });