Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add custom working directory to custom builder #4112

Merged
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
84 changes: 79 additions & 5 deletions samcli/lib/build/app_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,15 @@ def _build_layer(

# By default prefer to build in-process for speed
build_runtime = specified_workflow
options = ApplicationBuilder._get_build_options(layer_name, config.language, None)
options = ApplicationBuilder._get_build_options(
layer_name,
config.language,
self._base_dir,
None,
metadata=layer_metadata,
source_code_path=code_dir,
scratch_dir=scratch_dir,
)
if self._container_manager:
# None key represents the global build image for all functions/layers
if config.language == "provided":
Expand Down Expand Up @@ -646,7 +654,14 @@ def _build_function( # pylint: disable=R1710
)

options = ApplicationBuilder._get_build_options(
function_name, config.language, handler, config.dependency_manager, metadata
function_name,
config.language,
self._base_dir,
handler,
config.dependency_manager,
metadata,
source_code_path=code_dir,
scratch_dir=scratch_dir,
)
# By default prefer to build in-process for speed
if self._container_manager:
Expand Down Expand Up @@ -688,9 +703,12 @@ def _build_function( # pylint: disable=R1710
def _get_build_options(
function_name: str,
language: str,
base_dir: str,
handler: Optional[str],
dependency_manager: Optional[str] = None,
metadata: Optional[dict] = None,
source_code_path: Optional[str] = None,
scratch_dir: Optional[str] = None,
) -> Optional[Dict]:
"""
Parameters
Expand All @@ -699,12 +717,18 @@ def _get_build_options(
current function resource name
language str
language of the runtime
base_dir str
Path to a folder. Use this folder as the root to resolve relative source code paths against
handler str
Handler value of the Lambda Function Resource
dependency_manager str
Dependency manager to check in addition to language
metadata
metadata Dict
Metadata object to search for build properties
source_code_path str
The lambda function source code path that will be used to calculate the working directory
scratch_dir str
The temporary directory path where the lambda function code will be copied to.
Returns
-------
dict
Expand All @@ -723,12 +747,62 @@ def _get_build_options(
normalized_build_props["entry_points"] = entry_points
return normalized_build_props

_build_options: Dict = {
_build_options: Dict[str, Dict] = {
"go": {"artifact_executable_name": handler},
"provided": {"build_logical_id": function_name},
"nodejs": {"use_npm_ci": build_props.get("UseNpmCi", False)},
}
return _build_options.get(language, None)
options = _build_options.get(language, None)
if language == "provided":
options = options if options else {}
working_directory = ApplicationBuilder._get_working_directory_path(
base_dir, metadata, source_code_path, scratch_dir
)
if working_directory:
options = {**options, "working_directory": working_directory}
return options

@staticmethod
def _get_working_directory_path(
base_dir: str, metadata: Optional[Dict], source_code_path: Optional[str], scratch_dir: Optional[str]
) -> Optional[str]:
"""
Get the working directory from the lambda resource metadata information, and check if it is not None, and it
is a child path to the source directory path, then return the working directory as a child to the scratch
directory.
Parameters
----------
base_dir : str
Path to a folder. Use this folder as the root to resolve relative source code paths against
metadata Dict
Lambda resource metadata object to search for build properties
source_code_path str
The lambda resource source code path that will be used to calculate the working directory
scratch_dir str
The temporary directory path where the lambda resource code will be copied to.
Returns
-------
str
The working directory path or None if there is no working_dir metadata info.
"""
working_directory = None
if metadata and isinstance(metadata, dict):
working_directory = metadata.get("WorkingDirectory")
if working_directory:
working_directory = str(pathlib.Path(base_dir, working_directory).resolve())

# check if the working directory is a child of the lambda resource source code path, to update the
# working directory to be child of the scratch directory
if (
source_code_path
and scratch_dir
and os.path.commonpath([source_code_path, working_directory]) == os.path.normpath(source_code_path)
):
working_directory = os.path.relpath(working_directory, source_code_path)
working_directory = os.path.normpath(os.path.join(scratch_dir, working_directory))

return working_directory

def _build_function_in_process(
self,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Parameteres:
Runtime:
Type: String
CodeUri:
Type: String
Handler:
Type: String

Resources:

Function:
Type: AWS::Serverless::Function
Properties:
Handler: !Ref Handler
Runtime: !Ref Runtime
CodeUri: !Ref CodeUri
Timeout: 600
Metadata:
ContextPath: "./custom_root_dir_custom_makefile_and_custom_working_dir/custom_makefile"
ProjectRootDirectory: "./custom_root_dir_custom_makefile_and_custom_working_dir"
WorkingDirectory: "./custom_root_dir_custom_makefile_and_custom_working_dir/working_dir"
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Parameteres:
Runtime:
Type: String
CodeUri:
Type: String
Handler:
Type: String

Resources:

Function:
Type: AWS::Serverless::Function
Properties:
Handler: !Ref Handler
Runtime: !Ref Runtime
CodeUri: !Ref CodeUri
Timeout: 600
Metadata:
WorkingDirectory: "./custom_working_dir_src_code/working_dir"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build-Function:
cp *.py $(ARTIFACTS_DIR)
cp requirements.txt $(ARTIFACTS_DIR)
python -m pip install -r requirements.txt -t $(ARTIFACTS_DIR)
rm -rf $(ARTIFACTS_DIR)/bin
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import requests

def handler(event, context):
return requests.__version__
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requests==2.23.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build-Function:
cp *.py $(ARTIFACTS_DIR)
cp requirements.txt $(ARTIFACTS_DIR)
python -m pip install -r requirements.txt -t $(ARTIFACTS_DIR)
rm -rf $(ARTIFACTS_DIR)/bin
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import requests

def handler(event, context):
return requests.__version__
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requests==2.23.0
Loading