Skip to content

Commit b1e6624

Browse files
sriram-mvjfuss
authored andcommitted
Release: v0.2.0 (#95)
* Fix local package installation (#72) When packaging the dependencies only the first local package would be included in the final bundle. This change adds support for any number of local directory links to be treated as buildable dependencies. Tests were also added for the case of 1 or 2 local directory links specified in the requirements.txt. * fix: Remove tests from .whl file (bdist_wheel) (#90) * Add .NET Core builder support (#91) * feat(maven): Support for Java Maven builder (#87) * chore: version bump to 0.2.0 (#94)
1 parent 9bc19ca commit b1e6624

File tree

50 files changed

+1805
-5
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1805
-5
lines changed

.appveyor.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ install:
3030

3131
# setup go
3232
- rmdir c:\go /s /q
33-
- "choco install golang"
33+
- "choco install golang --version 1.11.5"
3434
- "choco install bzr"
3535
- "choco install dep"
3636
- setx PATH "C:\go\bin;C:\gopath\bin;C:\Program Files (x86)\Bazaar\;C:\Program Files\Mercurial;%PATH%;"
@@ -40,6 +40,9 @@ install:
4040
# setup Gradle
4141
- "choco install gradle"
4242

43+
# Echo final Path
44+
- "echo %PATH%"
45+
4346
test_script:
4447
- "%PYTHON%\\python.exe -m pytest --cov aws_lambda_builders --cov-report term-missing tests/unit tests/functional"
4548
- "%PYTHON%\\python.exe -m pytest tests/integration"

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,10 @@ GitHub.sublime-settings
360360
!.vscode/extensions.json
361361
.history
362362

363+
### .NET Build Folders ###
364+
**/bin/
365+
**/obj/
366+
363367
### Windows ###
364368
# Windows thumbnail cache files
365369
Thumbs.db

.travis.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ install:
2525

2626
- go get -u github.com/golang/dep/cmd/dep
2727

28+
# Install .NET Core 2.1
29+
- export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 DOTNET_CLI_TELEMETRY_OPTOUT=1
30+
- if [ "$LINUX" ]; then sudo apt install libunwind8; fi
31+
- wget https://dot.net/v1/dotnet-install.sh -O /tmp/dotnet-install.sh
32+
- chmod +x /tmp/dotnet-install.sh
33+
- /tmp/dotnet-install.sh -v 2.1.504
34+
- export DOTNET_ROOT=/home/travis/.dotnet
35+
- export PATH=/home/travis/.dotnet:/home/travis/.dotnet/tools:$PATH
36+
- dotnet --info
37+
2838
# Install the code requirements
2939
- make init
3040
script:

aws_lambda_builders/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
22
AWS Lambda Builder Library
33
"""
4-
__version__ = '0.1.0'
4+
__version__ = '0.2.0'
55
RPC_PROTOCOL_VERSION = "0.2"

aws_lambda_builders/workflows/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
import aws_lambda_builders.workflows.go_dep
99
import aws_lambda_builders.workflows.go_modules
1010
import aws_lambda_builders.workflows.java_gradle
11+
import aws_lambda_builders.workflows.java_maven
12+
import aws_lambda_builders.workflows.dotnet_clipackage
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# .NET Core - Lambda Builder
2+
3+
### Scope
4+
5+
To build .NET Core Lambda functions this builder will use the AWS .NET Core Global Tool [Amazon.Lambda.Tools](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools).
6+
This tool has several commands for building and publishing .NET Core Lambda functions. For this integration
7+
the `dotnet lambda package` command will be used to create a zip file that can be deployed to Lambda.
8+
9+
The builder will install the Amazon.Lambda.Tools Global Tool or update to the latest version before executing
10+
the package command.
11+
12+
This builder assumes the [.NET Core command-line interface (CLI)](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x)
13+
is already installed and added to the path environment variable. This is a reasonable requirement as the
14+
.NET Core CLI is a required tool for .NET Core developers to build any .NET Core project.
15+
16+
The .NET Core CLI handles the validation that the correct version of .NET Core is installed and errors out when there is
17+
not a correct version.
18+
19+
### Challenges
20+
21+
#### Output
22+
23+
The output of `dotnet lambda package` command is a zip archive that consumers can then deploy to Lambda. For SAM build
24+
the expected output is a directory of all of the output files. To make the package command compatible with the SAM build
25+
this builder will direct the package command to output the zip file in the artifacts folder. Once the package command is complete
26+
it expands the zip file and then deletes the zip file.
27+
28+
#### Parameters
29+
30+
The package command takes in serveral parameters. Here is the help for the package command.
31+
```bash
32+
> dotnet lambda package --help
33+
Amazon Lambda Tools for .NET Core applications (3.1.2)
34+
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet
35+
36+
package:
37+
Command to package a Lambda project into a zip file ready for deployment
38+
39+
dotnet lambda package [arguments] [options]
40+
Arguments:
41+
<ZIP-FILE> The name of the zip file to package the project into
42+
Options:
43+
-c | --configuration Configuration to build with, for example Release or Debug.
44+
-f | --framework Target framework to compile, for example netcoreapp2.1.
45+
--msbuild-parameters Additional msbuild parameters passed to the 'dotnet publish' command. Add quotes around the value if the value contains spaces.
46+
-pl | --project-location The location of the project, if not set the current directory will be assumed.
47+
-cfg | --config-file Configuration file storing default values for command line arguments.
48+
-pcfg | --persist-config-file If true the arguments used for a successful deployment are persisted to a config file.
49+
-o | --output-package The output zip file name
50+
-dvc | --disable-version-check Disable the .NET Core version check. Only for advanced usage.
51+
```
52+
53+
Currently **--framework** is the only required parameter which tells the underlying build process what version of .NET Core to build for.
54+
55+
Parameters can be passed into the package command either by a config file called **aws-lambda-tools-defaults.json** or on
56+
the command line. All .NET Core project templates provided by AWS contain the **aws-lambda-tools-defaults.json** file which has
57+
configuration and framework set.
58+
59+
If a parameter is set on the command line it will override any values set in the **aws-lambda-tools-defaults.json**.
60+
An alternative config file can be specified with the **--config-file** parameter.
61+
62+
This builder will forward any options that were provided to it starting with a '-' into the Lambda package command. Forwarding
63+
all parameters to the Lambda package command keeps the builder future compatible with changes to the package command. The package
64+
command does not error out for unknown parameters.
65+
66+
### Implementation
67+
68+
The implementation is broken up into 2 steps. The first action is to make sure the Amazon.Lambda.Tools Global Tool
69+
is installed. The second action is to execute the `dotnet lambda package` command.
70+
71+
#### Step 1: Install Amazon.Lambda.Tools
72+
73+
The tool is installed by executing the command `dotnet tool install -g Amazon.Lambda.Tools` This will install the
74+
tool from [NuGet](https://www.nuget.org/packages/Amazon.Lambda.Tools/) the .NET package management system.
75+
76+
To keep the tool updated the command `dotnet tool update -g Amazon.Lambda.Tools` will be executed if the install
77+
command fail because the tool was already installed.
78+
79+
It is a requirement for Amazon.Lambda.Tools to maintain backwards compatiblity for the package command. This is an
80+
existing requirement for compatiblity with PowerShell Lambda support and the AWS Tools for Visual Studio Team Services.
81+
82+
#### Step 2: Build the Lambda Deployment bundle
83+
84+
To create the Lambda deployment bundle the `dotnet lambda package` command is execute in the project directory. This will
85+
create zip file in the artifacts directory. The builder will then expand the zip file into the zip artifacts folder and
86+
delete the zip file.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""
2+
Builds .NET Core Lambda functions using Amazon.Lambda.Tools Global Tool https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools
3+
"""
4+
5+
from .workflow import DotnetCliPackageWorkflow
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""
2+
Actions for Ruby dependency resolution with Bundler
3+
"""
4+
5+
import os
6+
import logging
7+
8+
from aws_lambda_builders.actions import BaseAction, Purpose, ActionFailedError
9+
from .utils import OSUtils
10+
from .dotnetcli import DotnetCLIExecutionError
11+
12+
LOG = logging.getLogger(__name__)
13+
14+
class GlobalToolInstallAction(BaseAction):
15+
16+
"""
17+
A Lambda Builder Action which installs the Amazon.Lambda.Tools .NET Core Global Tool
18+
"""
19+
20+
NAME = 'GlobalToolInstall'
21+
DESCRIPTION = "Install or update the Amazon.Lambda.Tools .NET Core Global Tool."
22+
PURPOSE = Purpose.COMPILE_SOURCE
23+
24+
def __init__(self, subprocess_dotnet):
25+
super(GlobalToolInstallAction, self).__init__()
26+
self.subprocess_dotnet = subprocess_dotnet
27+
28+
def execute(self):
29+
try:
30+
LOG.debug("Installing Amazon.Lambda.Tools Global Tool")
31+
self.subprocess_dotnet.run(
32+
['tool', 'install', '-g', 'Amazon.Lambda.Tools'],
33+
)
34+
except DotnetCLIExecutionError as ex:
35+
LOG.debug("Error installing probably due to already installed. Attempt to update to latest version.")
36+
try:
37+
self.subprocess_dotnet.run(
38+
['tool', 'update', '-g', 'Amazon.Lambda.Tools'],
39+
)
40+
except DotnetCLIExecutionError as ex:
41+
raise ActionFailedError("Error configuring the Amazon.Lambda.Tools .NET Core Global Tool: " + str(ex))
42+
43+
class RunPackageAction(BaseAction):
44+
"""
45+
A Lambda Builder Action which builds the .NET Core project using the Amazon.Lambda.Tools .NET Core Global Tool
46+
"""
47+
48+
NAME = 'RunPackageAction'
49+
DESCRIPTION = "Execute the `dotnet lambda package` command."
50+
PURPOSE = Purpose.COMPILE_SOURCE
51+
52+
def __init__(self, source_dir, subprocess_dotnet, artifacts_dir, options, os_utils=None):
53+
super(RunPackageAction, self).__init__()
54+
self.source_dir = source_dir
55+
self.subprocess_dotnet = subprocess_dotnet
56+
self.artifacts_dir = artifacts_dir
57+
self.options = options
58+
self.os_utils = os_utils if os_utils else OSUtils()
59+
60+
def execute(self):
61+
try:
62+
LOG.debug("Running `dotnet lambda package` in %s", self.source_dir)
63+
64+
zipfilename = os.path.basename(os.path.normpath(self.source_dir)) + ".zip"
65+
zipfullpath = os.path.join(self.artifacts_dir, zipfilename)
66+
67+
arguments = ['lambda', 'package', '--output-package', zipfullpath]
68+
69+
if self.options is not None:
70+
for key in self.options:
71+
if str.startswith(key, "-"):
72+
arguments.append(key)
73+
arguments.append(self.options[key])
74+
75+
self.subprocess_dotnet.run(
76+
arguments,
77+
cwd=self.source_dir
78+
)
79+
80+
# The dotnet lambda package command outputs a zip file for the package. To make this compatible
81+
# with the workflow, unzip the zip file into the artifacts directory and then delete the zip archive.
82+
self.os_utils.expand_zip(zipfullpath, self.artifacts_dir)
83+
84+
except DotnetCLIExecutionError as ex:
85+
raise ActionFailedError(str(ex))
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""
2+
Wrapper around calls to dotent CLI through a subprocess.
3+
"""
4+
5+
import sys
6+
import logging
7+
8+
from .utils import OSUtils
9+
10+
LOG = logging.getLogger(__name__)
11+
12+
class DotnetCLIExecutionError(Exception):
13+
"""
14+
Exception raised when dotnet CLI fails.
15+
Will encapsulate error output from the command.
16+
"""
17+
18+
MESSAGE = "Dotnet CLI Failed: {message}"
19+
20+
def __init__(self, **kwargs):
21+
Exception.__init__(self, self.MESSAGE.format(**kwargs))
22+
23+
class SubprocessDotnetCLI(object):
24+
"""
25+
Wrapper around the Dotnet CLI, encapsulating
26+
execution results.
27+
"""
28+
29+
def __init__(self, dotnet_exe=None, os_utils=None):
30+
self.os_utils = os_utils if os_utils else OSUtils()
31+
if dotnet_exe is None:
32+
if self.os_utils.is_windows():
33+
dotnet_exe = 'dotnet.exe'
34+
else:
35+
dotnet_exe = 'dotnet'
36+
37+
self.dotnet_exe = dotnet_exe
38+
39+
def run(self, args, cwd=None):
40+
if not isinstance(args, list):
41+
raise ValueError('args must be a list')
42+
43+
if not args:
44+
raise ValueError('requires at least one arg')
45+
46+
invoke_dotnet = [self.dotnet_exe] + args
47+
48+
LOG.debug("executing dotnet: %s", invoke_dotnet)
49+
50+
p = self.os_utils.popen(invoke_dotnet,
51+
stdout=self.os_utils.pipe,
52+
stderr=self.os_utils.pipe,
53+
cwd=cwd)
54+
55+
out, err = p.communicate()
56+
57+
# The package command contains lots of useful information on how the package was created and
58+
# information when the package command was not successful. For that reason the output is
59+
# always written to the output to help developers diagnose issues.
60+
LOG.info(out.decode('utf8').strip())
61+
62+
if p.returncode != 0:
63+
raise DotnetCLIExecutionError(message=err.decode('utf8').strip())
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
Dotnet executable resolution
3+
"""
4+
5+
from .utils import OSUtils
6+
7+
class DotnetCliResolver(object):
8+
9+
def __init__(self, executable_search_paths=None, os_utils=None):
10+
self.binary = 'dotnet'
11+
self.executable_search_paths = executable_search_paths
12+
self.os_utils = os_utils if os_utils else OSUtils()
13+
14+
@property
15+
def exec_paths(self):
16+
17+
# look for the windows executable
18+
paths = self.os_utils.which('dotnet.exe', executable_search_paths=self.executable_search_paths)
19+
if not paths:
20+
# fallback to the non windows name without the .exe suffix
21+
paths = self.os_utils.which('dotnet', executable_search_paths=self.executable_search_paths)
22+
23+
if not paths:
24+
raise ValueError("No dotnet cli executable found!")
25+
26+
return paths

0 commit comments

Comments
 (0)