From aaa640365f2ea073922ea7e9f73007b6912c0b4c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Jul 2026 11:19:44 +0000 Subject: [PATCH 1/9] Initial plan From 4df607a3c85f4f82b8dd56cc5abddc112c2fec28 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Jul 2026 11:22:30 +0000 Subject: [PATCH 2/9] Add apptainer script action dispatch --- mlc/main.py | 2 +- mlc/script_action.py | 13 +++++++++++-- tests/test_script_action_apptainer.py | 28 +++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/test_script_action_apptainer.py diff --git a/mlc/main.py b/mlc/main.py index 0250ad303..8c0f311fa 100644 --- a/mlc/main.py +++ b/mlc/main.py @@ -507,7 +507,7 @@ def main(): | Target | Actions | |---------|-----------------------------------------------------------| - | script | run, find/search, rm, mv, cp, add, test, docker-run, show | + | script | run, find/search, rm, mv, cp, add, test, docker-run, apptainer, show | | cache | find/search, rm, show, list, prune, mark-tmp | | repo | pull, search, rm, list, find/search | diff --git a/mlc/script_action.py b/mlc/script_action.py index bee4d9f00..99f2c8d33 100644 --- a/mlc/script_action.py +++ b/mlc/script_action.py @@ -26,8 +26,9 @@ class ScriptAction(Action): 6. Copy(cp) 7. Run 8. Docker - 9. Test - 10. Experiment + 9. Apptainer + 10. Test + 11. Experiment Scripts in MLCFlow can be identified using different methods: @@ -414,6 +415,14 @@ def docker_run(self, run_args): docker.__doc__ = docker_run.__doc__ + def apptainer(self, run_args): + return self.apptainer_run(run_args) + + def apptainer_run(self, run_args): + return self.call_script_module_function("apptainer", run_args) + + apptainer.__doc__ = docker_run.__doc__ + def remote_run(self, run_args): """ #################################################################################################################### diff --git a/tests/test_script_action_apptainer.py b/tests/test_script_action_apptainer.py new file mode 100644 index 000000000..27b2bd27c --- /dev/null +++ b/tests/test_script_action_apptainer.py @@ -0,0 +1,28 @@ +import unittest +from unittest.mock import patch + +from mlc.script_action import ScriptAction + + +class _Parent: + pass + + +class ScriptActionApptainerTest(unittest.TestCase): + def test_apptainer_delegates_to_script_module(self): + action = ScriptAction(_Parent()) + run_args = {"tags": "detect,os"} + expected = {"return": 0} + + with patch.object( + ScriptAction, + "call_script_module_function", + return_value=expected) as call_script_module_function: + result = action.apptainer(run_args) + + self.assertEqual(result, expected) + call_script_module_function.assert_called_once_with("apptainer", run_args) + + +if __name__ == "__main__": + unittest.main() From 100a42e7d42c709442e17e1b470dc09d2d6b2ec6 Mon Sep 17 00:00:00 2001 From: mlc-automations <3246381+mlc-automations@users.noreply.github.com> Date: Sat, 4 Jul 2026 11:24:33 +0000 Subject: [PATCH 3/9] [Automated Commit] Format Codebase --- tests/test_script_action_apptainer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_script_action_apptainer.py b/tests/test_script_action_apptainer.py index 27b2bd27c..23403ebe1 100644 --- a/tests/test_script_action_apptainer.py +++ b/tests/test_script_action_apptainer.py @@ -21,7 +21,8 @@ def test_apptainer_delegates_to_script_module(self): result = action.apptainer(run_args) self.assertEqual(result, expected) - call_script_module_function.assert_called_once_with("apptainer", run_args) + call_script_module_function.assert_called_once_with( + "apptainer", run_args) if __name__ == "__main__": From 55c2d56cbc668aae39a06cc53f5e7ddea0fa6c61 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Jul 2026 11:24:43 +0000 Subject: [PATCH 4/9] Handle apptainer dispatch in ScriptAction --- mlc/script_action.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/mlc/script_action.py b/mlc/script_action.py index 99f2c8d33..9de4dcce4 100644 --- a/mlc/script_action.py +++ b/mlc/script_action.py @@ -286,6 +286,9 @@ def call_script_module_function(self, function_name, run_args): elif function_name == "docker": result = automation_instance.docker( run_args) # Pass args to the run method + elif function_name == "apptainer": + result = automation_instance.apptainer( + run_args) # Pass args to the apptainer method elif function_name == "test": result = automation_instance.test( run_args) # Pass args to the run method @@ -419,9 +422,28 @@ def apptainer(self, run_args): return self.apptainer_run(run_args) def apptainer_run(self, run_args): + """ + #################################################################################################################### + Target: Script + Action: Apptainer + #################################################################################################################### + + The `apptainer` action runs scripts inside an Apptainer containerized environment. + + An MLCFlow script can be executed inside Apptainer using either of the following syntaxes: + + 1. Apptainer Run: mlc apptainer run --tags=