Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/fixed-20260607-135834.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: fixed
body: Clean up temporary file after table maintenance job execution
time: 2026-06-07T13:58:34+02:00
custom:
Author: iemejia
AuthorLink: https://github.com/iemejia
18 changes: 14 additions & 4 deletions src/fabric_cli/commands/tables/fab_tables_opt.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import contextlib
import json
import os
import tempfile
from argparse import Namespace

Expand All @@ -19,10 +21,18 @@ def exec_command(args: Namespace) -> None:
_config["schemaName"] = args.schema

with tempfile.NamedTemporaryFile(delete=False) as temp_file:
with open(temp_file.name, "w") as fp:
temp_path = temp_file.name
with open(temp_path, "w") as fp:
json.dump(_config, fp)

args.configuration = None
args.input = temp_file.name
args.params = None
# Run outside the with block so the temp file handle is closed first,
# which is required for deletion to succeed on Windows.
args.configuration = None
args.input = temp_path
args.params = None

try:
jobs.run_command(args)
finally:
with contextlib.suppress(OSError):
os.unlink(temp_path)
105 changes: 105 additions & 0 deletions tests/test_core/test_fab_tables_opt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import json
import os
from argparse import Namespace
from unittest.mock import patch

import pytest

from fabric_cli.commands.tables import fab_tables_opt


def test_exec_command_cleans_up_temp_file():
"""Verify the temporary config file is removed after job execution."""
args = Namespace(
jobType=None,
lakehouse_path="/workspace/lakehouse",
jobs_command=None,
configuration='{"optimize": true}',
table_name="my_table",
schema=None,
input=None,
params=None,
path=None,
)

created_temp_files = []

def mock_run_command(a):
# Capture the temp file path before it gets cleaned up
created_temp_files.append(a.input)
assert os.path.exists(a.input), "Temp file should exist during job execution"

with patch(
"fabric_cli.commands.tables.fab_tables_opt.jobs.run_command",
side_effect=mock_run_command,
):
fab_tables_opt.exec_command(args)

assert len(created_temp_files) == 1
assert not os.path.exists(
created_temp_files[0]
), "Temp file should be cleaned up after job execution"


def test_exec_command_cleans_up_temp_file_on_error():
"""Verify the temporary config file is removed even if the job fails."""
args = Namespace(
jobType=None,
lakehouse_path="/workspace/lakehouse",
jobs_command=None,
configuration='{"optimize": true}',
table_name="my_table",
schema=None,
input=None,
params=None,
path=None,
)

created_temp_files = []

def mock_run_command(a):
created_temp_files.append(a.input)
raise RuntimeError("Job failed")

with patch(
"fabric_cli.commands.tables.fab_tables_opt.jobs.run_command",
side_effect=mock_run_command,
):
with pytest.raises(RuntimeError, match="Job failed"):
fab_tables_opt.exec_command(args)

assert len(created_temp_files) == 1
assert not os.path.exists(
created_temp_files[0]
), "Temp file should be cleaned up even when job fails"


def test_exec_command_writes_correct_config_to_temp_file():
"""Verify the temp file contains the expected job configuration."""
args = Namespace(
jobType=None,
lakehouse_path="/workspace/lakehouse",
jobs_command=None,
configuration='{"optimize": true}',
table_name="sales",
schema="dbo",
input=None,
params=None,
path=None,
)

def mock_run_command(a):
with open(a.input, "r") as f:
config = json.load(f)
assert config["tableName"] == "sales"
assert config["schemaName"] == "dbo"
assert config["optimize"] is True

with patch(
"fabric_cli.commands.tables.fab_tables_opt.jobs.run_command",
side_effect=mock_run_command,
):
fab_tables_opt.exec_command(args)
Loading