diff --git a/sagemaker-train/src/sagemaker/train/common_utils/finetune_utils.py b/sagemaker-train/src/sagemaker/train/common_utils/finetune_utils.py index 9048204cc6..8e4734f01b 100644 --- a/sagemaker-train/src/sagemaker/train/common_utils/finetune_utils.py +++ b/sagemaker-train/src/sagemaker/train/common_utils/finetune_utils.py @@ -12,6 +12,9 @@ from sagemaker.core.helper.session_helper import Session from sagemaker.core.s3.utils import resolve_s3_uri_placeholders from sagemaker.train.common_utils.recipe_utils import _get_hub_content_metadata +# Single source of truth for Lambda-ARN detection, shared with the reward verifier +# so both code paths agree on what counts as a Lambda ARN. +from sagemaker.train.common_utils.rlvr_reward_verifier import LAMBDA_ARN_REGEX from sagemaker.train.common import TrainingType, CustomizationTechnique, JOB_TYPE, FineTuningOptions from sagemaker.core.shapes import ServerlessJobConfig, Channel, DataSource, ModelPackageConfig, MlflowConfig from sagemaker.core.training.configs import HyperPodCompute, TrainingJobCompute diff --git a/sagemaker-train/tests/unit/train/common_utils/test_finetune_utils.py b/sagemaker-train/tests/unit/train/common_utils/test_finetune_utils.py index ead56fa65d..c69cbd07d7 100644 --- a/sagemaker-train/tests/unit/train/common_utils/test_finetune_utils.py +++ b/sagemaker-train/tests/unit/train/common_utils/test_finetune_utils.py @@ -16,6 +16,7 @@ _get_default_s3_output_path, _extract_dataset_source, _extract_evaluator_arn, + _is_lambda_arn, _resolve_model_name, _resolve_model_package_arn, _get_fine_tuning_options_and_model_arn, @@ -1332,3 +1333,33 @@ def test_missing_hyperpod_cli_raises_runtime_error( fu.get_hyperpod_recipe_path( "nova-lite", "SFT", "LORA", session, job_name="myjob" ) + + +class TestIsLambdaArn: + """Regression coverage for _is_lambda_arn (the LAMBDA_ARN_REGEX constant + was previously undefined, raising NameError at call time).""" + + def test_valid_lambda_arn(self): + assert _is_lambda_arn( + "arn:aws:lambda:us-west-2:123456789012:function:my-reward-fn" + ) is True + + def test_valid_lambda_arn_aws_partition_variants(self): + assert _is_lambda_arn( + "arn:aws-us-gov:lambda:us-gov-west-1:123456789012:function:fn" + ) is True + + def test_evaluator_hub_content_arn_is_not_lambda(self): + assert _is_lambda_arn( + "arn:aws:sagemaker:us-west-2:123456789012:hub-content/" + "SageMakerPublicHub/JsonDoc/my-evaluator/1.0" + ) is False + + def test_arbitrary_string_is_not_lambda(self): + assert _is_lambda_arn("not-an-arn") is False + + def test_uses_shared_regex_from_reward_verifier(self): + # Both call sites must agree on what a Lambda ARN is; assert they + # share the same compiled pattern rather than diverging copies. + from sagemaker.train.common_utils import rlvr_reward_verifier + assert fu.LAMBDA_ARN_REGEX is rlvr_reward_verifier.LAMBDA_ARN_REGEX