diff --git a/__test__/blacksmith-cache.test.ts b/__test__/blacksmith-cache.test.ts index 98ef507..51afe34 100644 --- a/__test__/blacksmith-cache.test.ts +++ b/__test__/blacksmith-cache.test.ts @@ -132,6 +132,49 @@ describe('blacksmith-cache tests', () => { }) }) + describe('shouldUseBlacksmithCache', () => { + const originalEnv = process.env + + beforeEach(() => { + jest.resetModules() + process.env = {...originalEnv} + }) + + afterAll(() => { + process.env = originalEnv + }) + + it('returns true when in Blacksmith env and kill switch is unset', () => { + process.env['BLACKSMITH_VM_ID'] = 'test-vm-id' + delete process.env['BLACKSMITH_BYPASS_CHECKOUT'] + expect(blacksmithCache.shouldUseBlacksmithCache()).toBe(true) + }) + + it('returns false outside of a Blacksmith env regardless of kill switch', () => { + delete process.env['BLACKSMITH_VM_ID'] + process.env['BLACKSMITH_BYPASS_CHECKOUT'] = 'true' + expect(blacksmithCache.shouldUseBlacksmithCache()).toBe(false) + }) + + it('returns false when BLACKSMITH_BYPASS_CHECKOUT=true (control-plane kill switch)', () => { + process.env['BLACKSMITH_VM_ID'] = 'test-vm-id' + process.env['BLACKSMITH_BYPASS_CHECKOUT'] = 'true' + expect(blacksmithCache.shouldUseBlacksmithCache()).toBe(false) + }) + + it('returns true when BLACKSMITH_BYPASS_CHECKOUT is any value other than "true"', () => { + process.env['BLACKSMITH_VM_ID'] = 'test-vm-id' + process.env['BLACKSMITH_BYPASS_CHECKOUT'] = 'false' + expect(blacksmithCache.shouldUseBlacksmithCache()).toBe(true) + + process.env['BLACKSMITH_BYPASS_CHECKOUT'] = '1' + expect(blacksmithCache.shouldUseBlacksmithCache()).toBe(true) + + process.env['BLACKSMITH_BYPASS_CHECKOUT'] = '' + expect(blacksmithCache.shouldUseBlacksmithCache()).toBe(true) + }) + }) + describe('multiple checkout scenario', () => { it('each repo gets isolated paths that do not conflict', () => { // Simulate the multiple checkout scenario from the customer issue: diff --git a/dist/index.js b/dist/index.js index e315dfe..46de4b6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -41,6 +41,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getMountPoint = getMountPoint; exports.isBlacksmithEnvironment = isBlacksmithEnvironment; +exports.shouldUseBlacksmithCache = shouldUseBlacksmithCache; exports.getMirrorPath = getMirrorPath; exports.setupCache = setupCache; exports.ensureMirror = ensureMirror; @@ -83,6 +84,24 @@ function getMountPoint(owner, repo) { function isBlacksmithEnvironment() { return !!process.env.BLACKSMITH_VM_ID; } +/** + * Control plane short circuit: when an installation has the + * `bypass_blacksmith_checkout` flag flipped on, the agent exports + * BLACKSMITH_BYPASS_CHECKOUT=true into the runner environment. We + * use that as a kill switch to skip every Blacksmith-specific code path + * (mirror cache setup, alternates, dissociate, post-step commit). The + * action then behaves identically to upstream actions/checkout. + */ +function shouldUseBlacksmithCache() { + if (!isBlacksmithEnvironment()) { + return false; + } + if (process.env.BLACKSMITH_BYPASS_CHECKOUT === 'true') { + core.info('[blacksmith] BLACKSMITH_BYPASS_CHECKOUT=true — skipping Blacksmith git mirror cache and falling back to actions/checkout behavior'); + return false; + } + return true; +} /** * Get the path where the bare git mirror will be stored. * Uses owner-repo.git filename to maintain backward compatibility with existing sticky disks. @@ -2186,9 +2205,13 @@ function getSource(settings) { } // Save state for POST action stateHelper.setRepositoryPath(settings.repositoryPath); - // Setup Blacksmith git mirror cache if in Blacksmith environment + // Setup Blacksmith git mirror cache if in Blacksmith environment. + // shouldUseBlacksmithCache() honors the BLACKSMITH_BYPASS_CHECKOUT + // kill switch (driven by the per-installation flag in the control plane), + // so flipping that flag disables the entire Blacksmith code path here + // and in the post step. let cacheInfo = null; - if (blacksmithCache.isBlacksmithEnvironment()) { + if (blacksmithCache.shouldUseBlacksmithCache()) { try { core.startGroup('Setting up Blacksmith git mirror cache'); cacheInfo = yield blacksmithCache.setupCache(settings.repositoryOwner, settings.repositoryName); diff --git a/src/blacksmith-cache.ts b/src/blacksmith-cache.ts index 3411016..39be695 100644 --- a/src/blacksmith-cache.ts +++ b/src/blacksmith-cache.ts @@ -71,6 +71,27 @@ export function isBlacksmithEnvironment(): boolean { return !!process.env.BLACKSMITH_VM_ID } +/** + * Control plane short circuit: when an installation has the + * `bypass_blacksmith_checkout` flag flipped on, the agent exports + * BLACKSMITH_BYPASS_CHECKOUT=true into the runner environment. We + * use that as a kill switch to skip every Blacksmith-specific code path + * (mirror cache setup, alternates, dissociate, post-step commit). The + * action then behaves identically to upstream actions/checkout. + */ +export function shouldUseBlacksmithCache(): boolean { + if (!isBlacksmithEnvironment()) { + return false + } + if (process.env.BLACKSMITH_BYPASS_CHECKOUT === 'true') { + core.info( + '[blacksmith] BLACKSMITH_BYPASS_CHECKOUT=true — skipping Blacksmith git mirror cache and falling back to actions/checkout behavior' + ) + return false + } + return true +} + /** * Get the path where the bare git mirror will be stored. * Uses owner-repo.git filename to maintain backward compatibility with existing sticky disks. diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index 793fa4b..d7b1422 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -106,9 +106,13 @@ export async function getSource(settings: IGitSourceSettings): Promise { // Save state for POST action stateHelper.setRepositoryPath(settings.repositoryPath) - // Setup Blacksmith git mirror cache if in Blacksmith environment + // Setup Blacksmith git mirror cache if in Blacksmith environment. + // shouldUseBlacksmithCache() honors the BLACKSMITH_BYPASS_CHECKOUT + // kill switch (driven by the per-installation flag in the control plane), + // so flipping that flag disables the entire Blacksmith code path here + // and in the post step. let cacheInfo: blacksmithCache.CacheInfo | null = null - if (blacksmithCache.isBlacksmithEnvironment()) { + if (blacksmithCache.shouldUseBlacksmithCache()) { try { core.startGroup('Setting up Blacksmith git mirror cache') cacheInfo = await blacksmithCache.setupCache(