fix: keep response-file temp file for downstream steps
The temporary file created for response-file was being cleaned up before downstream steps could access it. Now using keep: true to ensure the file persists until the job completes. Also added script/ to eslint ignores for the mock server.
This commit is contained in:
+4
-26
@@ -75,17 +75,13 @@ vi.mock('fs', () => ({
|
|||||||
writeFileSync: mockWriteFileSync,
|
writeFileSync: mockWriteFileSync,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Mocks for tmp module to control temporary file creation and cleanup
|
// Mocks for tmp module to control temporary file creation
|
||||||
const mockRemoveCallback = vi.fn()
|
|
||||||
const mockFileSync = vi.fn().mockReturnValue({
|
const mockFileSync = vi.fn().mockReturnValue({
|
||||||
name: '/secure/temp/dir/modelResponse-abc123.txt',
|
name: '/secure/temp/dir/modelResponse-abc123.txt',
|
||||||
removeCallback: mockRemoveCallback,
|
|
||||||
})
|
})
|
||||||
const mockSetGracefulCleanup = vi.fn()
|
|
||||||
|
|
||||||
vi.mock('tmp', () => ({
|
vi.mock('tmp', () => ({
|
||||||
fileSync: mockFileSync,
|
fileSync: mockFileSync,
|
||||||
setGracefulCleanup: mockSetGracefulCleanup,
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Mock MCP and inference modules
|
// Mock MCP and inference modules
|
||||||
@@ -283,7 +279,7 @@ describe('main.ts', () => {
|
|||||||
expect(mockProcessExit).toHaveBeenCalledWith(1)
|
expect(mockProcessExit).toHaveBeenCalledWith(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('creates secure temporary files with proper cleanup', async () => {
|
it('creates temporary files that persist for downstream steps', async () => {
|
||||||
mockInputs({
|
mockInputs({
|
||||||
prompt: 'Test prompt',
|
prompt: 'Test prompt',
|
||||||
'system-prompt': 'You are a test assistant.',
|
'system-prompt': 'You are a test assistant.',
|
||||||
@@ -291,34 +287,16 @@ describe('main.ts', () => {
|
|||||||
|
|
||||||
await run()
|
await run()
|
||||||
|
|
||||||
expect(mockSetGracefulCleanup).toHaveBeenCalledOnce()
|
// Verify temp file is created with keep: true so it persists
|
||||||
|
|
||||||
expect(mockFileSync).toHaveBeenCalledWith({
|
expect(mockFileSync).toHaveBeenCalledWith({
|
||||||
prefix: 'modelResponse-',
|
prefix: 'modelResponse-',
|
||||||
postfix: '.txt',
|
postfix: '.txt',
|
||||||
|
keep: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'response-file', '/secure/temp/dir/modelResponse-abc123.txt')
|
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'response-file', '/secure/temp/dir/modelResponse-abc123.txt')
|
||||||
expect(mockWriteFileSync).toHaveBeenCalledWith('/secure/temp/dir/modelResponse-abc123.txt', 'Hello, user!', 'utf-8')
|
expect(mockWriteFileSync).toHaveBeenCalledWith('/secure/temp/dir/modelResponse-abc123.txt', 'Hello, user!', 'utf-8')
|
||||||
expect(mockRemoveCallback).toHaveBeenCalledOnce()
|
|
||||||
|
|
||||||
expect(mockProcessExit).toHaveBeenCalledWith(0)
|
expect(mockProcessExit).toHaveBeenCalledWith(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handles cleanup errors gracefully', async () => {
|
|
||||||
mockRemoveCallback.mockImplementationOnce(() => {
|
|
||||||
throw new Error('Cleanup failed')
|
|
||||||
})
|
|
||||||
|
|
||||||
mockInputs({
|
|
||||||
prompt: 'Test prompt',
|
|
||||||
'system-prompt': 'You are a test assistant.',
|
|
||||||
})
|
|
||||||
|
|
||||||
await run()
|
|
||||||
|
|
||||||
expect(mockRemoveCallback).toHaveBeenCalledOnce()
|
|
||||||
expect(core.warning).toHaveBeenCalledWith('Failed to cleanup temporary file: Error: Cleanup failed')
|
|
||||||
expect(mockProcessExit).toHaveBeenCalledWith(0)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|||||||
+5
-17
@@ -52618,9 +52618,6 @@ function isPromptYamlFile(filePath) {
|
|||||||
* @returns Resolves when the action is complete.
|
* @returns Resolves when the action is complete.
|
||||||
*/
|
*/
|
||||||
async function run() {
|
async function run() {
|
||||||
let responseFile = null;
|
|
||||||
// Set up graceful cleanup for temporary files on process exit
|
|
||||||
tmpExports.setGracefulCleanup();
|
|
||||||
try {
|
try {
|
||||||
const promptFilePath = coreExports.getInput('prompt-file');
|
const promptFilePath = coreExports.getInput('prompt-file');
|
||||||
const inputVariables = coreExports.getInput('input');
|
const inputVariables = coreExports.getInput('input');
|
||||||
@@ -52675,10 +52672,13 @@ async function run() {
|
|||||||
modelResponse = await simpleInference(inferenceRequest);
|
modelResponse = await simpleInference(inferenceRequest);
|
||||||
}
|
}
|
||||||
coreExports.setOutput('response', modelResponse || '');
|
coreExports.setOutput('response', modelResponse || '');
|
||||||
// Create a secure temporary file instead of using the temp directory directly
|
// Create a temporary file for the response that persists for downstream steps.
|
||||||
responseFile = tmpExports.fileSync({
|
// We use keep: true to prevent automatic cleanup - the file will be cleaned up
|
||||||
|
// by the runner when the job completes.
|
||||||
|
const responseFile = tmpExports.fileSync({
|
||||||
prefix: 'modelResponse-',
|
prefix: 'modelResponse-',
|
||||||
postfix: '.txt',
|
postfix: '.txt',
|
||||||
|
keep: true,
|
||||||
});
|
});
|
||||||
coreExports.setOutput('response-file', responseFile.name);
|
coreExports.setOutput('response-file', responseFile.name);
|
||||||
if (modelResponse && modelResponse !== '') {
|
if (modelResponse && modelResponse !== '') {
|
||||||
@@ -52695,18 +52695,6 @@ async function run() {
|
|||||||
// Force exit to prevent hanging on open connections
|
// Force exit to prevent hanging on open connections
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
// Explicit cleanup of temporary file if it was created
|
|
||||||
if (responseFile) {
|
|
||||||
try {
|
|
||||||
responseFile.removeCallback();
|
|
||||||
}
|
|
||||||
catch (cleanupError) {
|
|
||||||
// Log cleanup errors but don't fail the action
|
|
||||||
coreExports.warning(`Failed to cleanup temporary file: ${cleanupError}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Force exit to prevent hanging on open connections
|
// Force exit to prevent hanging on open connections
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -19,7 +19,7 @@ const compat = new FlatCompat({
|
|||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
ignores: ['**/coverage', '**/dist', '**/linter', '**/node_modules'],
|
ignores: ['**/coverage', '**/dist', '**/linter', '**/node_modules', 'script/**'],
|
||||||
},
|
},
|
||||||
...compat.extends(
|
...compat.extends(
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
|
|||||||
+5
-17
@@ -18,11 +18,6 @@ import {
|
|||||||
* @returns Resolves when the action is complete.
|
* @returns Resolves when the action is complete.
|
||||||
*/
|
*/
|
||||||
export async function run(): Promise<void> {
|
export async function run(): Promise<void> {
|
||||||
let responseFile: tmp.FileResult | null = null
|
|
||||||
|
|
||||||
// Set up graceful cleanup for temporary files on process exit
|
|
||||||
tmp.setGracefulCleanup()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const promptFilePath = core.getInput('prompt-file')
|
const promptFilePath = core.getInput('prompt-file')
|
||||||
const inputVariables = core.getInput('input')
|
const inputVariables = core.getInput('input')
|
||||||
@@ -101,10 +96,13 @@ export async function run(): Promise<void> {
|
|||||||
|
|
||||||
core.setOutput('response', modelResponse || '')
|
core.setOutput('response', modelResponse || '')
|
||||||
|
|
||||||
// Create a secure temporary file instead of using the temp directory directly
|
// Create a temporary file for the response that persists for downstream steps.
|
||||||
responseFile = tmp.fileSync({
|
// We use keep: true to prevent automatic cleanup - the file will be cleaned up
|
||||||
|
// by the runner when the job completes.
|
||||||
|
const responseFile = tmp.fileSync({
|
||||||
prefix: 'modelResponse-',
|
prefix: 'modelResponse-',
|
||||||
postfix: '.txt',
|
postfix: '.txt',
|
||||||
|
keep: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
core.setOutput('response-file', responseFile.name)
|
core.setOutput('response-file', responseFile.name)
|
||||||
@@ -120,16 +118,6 @@ export async function run(): Promise<void> {
|
|||||||
}
|
}
|
||||||
// Force exit to prevent hanging on open connections
|
// Force exit to prevent hanging on open connections
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
} finally {
|
|
||||||
// Explicit cleanup of temporary file if it was created
|
|
||||||
if (responseFile) {
|
|
||||||
try {
|
|
||||||
responseFile.removeCallback()
|
|
||||||
} catch (cleanupError) {
|
|
||||||
// Log cleanup errors but don't fail the action
|
|
||||||
core.warning(`Failed to cleanup temporary file: ${cleanupError}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force exit to prevent hanging on open connections
|
// Force exit to prevent hanging on open connections
|
||||||
|
|||||||
Reference in New Issue
Block a user