-
Notifications
You must be signed in to change notification settings - Fork 148
Golang Dep Builder #54
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
Merged
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
99d0242
Starts intial golang builder
448f4d9
adds generic repeated code
e336817
uses new actions
695e00f
cleans up actions
e209e31
adds actual test for actions
22f5ac2
moves os.environ to the utils class
6d20367
passes environ arg to go build action
414ae82
adds action tests
d161df9
empty test exec class
e1dcb4d
adds tests copied from the npm workflow
0f7f433
adds integration tests
4741a1c
adds func tests
17af331
change test class name
sthulb 946cf76
appveyor setup
sthulb f1c0afd
ensures the environment is a copy.
sthulb 4a1ce17
ignores vendor from tests
sthulb 3e75b33
moves ignore
sthulb 3e87f0f
reintroduces the sys version check
sthulb e036153
updates path for windows to include the old path
sthulb af4e2e4
moves pkgs to choco
sthulb eedaba3
fixes setx
sthulb a1cba83
Replaces sys.version check with something more reliable
sthulb 6ec1f7d
adds back the decode on stdout
sthulb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
""" | ||
Builds Go Lambda functions using the `dep` dependency manager | ||
""" | ||
|
||
from .workflow import GoDepWorkflow |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
""" | ||
Actions for Go dependency resolution with dep | ||
""" | ||
|
||
import logging | ||
import os | ||
|
||
from aws_lambda_builders.actions import BaseAction, Purpose, ActionFailedError | ||
|
||
from .subproc_exec import ExecutionError | ||
|
||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
class DepEnsureAction(BaseAction): | ||
|
||
""" | ||
A Lambda Builder Action which runs dep to install dependencies from Gopkg.toml | ||
""" | ||
|
||
NAME = "DepEnsure" | ||
DESCRIPTION = "Ensures all dependencies are installed for a project" | ||
PURPOSE = Purpose.RESOLVE_DEPENDENCIES | ||
|
||
def __init__(self, base_dir, subprocess_dep): | ||
super(DepEnsureAction, self).__init__() | ||
|
||
self.base_dir = base_dir | ||
self.subprocess_dep = subprocess_dep | ||
|
||
def execute(self): | ||
try: | ||
self.subprocess_dep.run(["ensure"], | ||
cwd=self.base_dir) | ||
except ExecutionError as ex: | ||
raise ActionFailedError(str(ex)) | ||
|
||
class GoBuildAction(BaseAction): | ||
|
||
""" | ||
A Lambda Builder Action which runs `go build` to create a binary | ||
""" | ||
|
||
NAME = "GoBuild" | ||
DESCRIPTION = "Builds final binary" | ||
PURPOSE = Purpose.COMPILE_SOURCE | ||
|
||
def __init__(self, base_dir, source_path, output_path, subprocess_go, env=None): | ||
super(GoBuildAction, self).__init__() | ||
|
||
self.base_dir = base_dir | ||
self.source_path = source_path | ||
self.output_path = output_path | ||
|
||
self.subprocess_go = subprocess_go | ||
self.env = env if not env is None else {} | ||
|
||
def execute(self): | ||
env = self.env | ||
env.update({"GOOS": "linux", "GOARCH": "amd64"}) | ||
|
||
try: | ||
self.subprocess_go.run(["build", "-o", self.output_path, self.source_path], | ||
sthulb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
cwd=self.source_path, env=env) | ||
except ExecutionError as ex: | ||
raise ActionFailedError(str(ex)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
""" | ||
Wrapper around calling dep through a subprocess. | ||
""" | ||
|
||
import logging | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
|
||
class ExecutionError(Exception): | ||
""" | ||
Exception raised in case binary execution fails. | ||
It will pass on the standard error output from the binary console. | ||
""" | ||
|
||
MESSAGE = "Exec Failed: {}" | ||
|
||
def __init__(self, message): | ||
raw_message = message | ||
if isinstance(message, bytes): | ||
message = message.decode('utf-8') | ||
|
||
try: | ||
Exception.__init__(self, self.MESSAGE.format(message.strip())) | ||
except UnicodeError: | ||
Exception.__init__(self, self.MESSAGE.format(raw_message.strip())) | ||
|
||
class SubprocessExec(object): | ||
|
||
""" | ||
Wrapper around the Dep command line utility, making it | ||
easy to consume execution results. | ||
""" | ||
|
||
def __init__(self, osutils, binary=None): | ||
""" | ||
:type osutils: aws_lambda_builders.workflows.go_dep.utils.OSUtils | ||
:param osutils: An instance of OS Utilities for file manipulation | ||
|
||
:type binary: str | ||
:param binary: Path to the binary. If not set, | ||
the default executable path will be used | ||
""" | ||
self.osutils = osutils | ||
|
||
self.binary = binary | ||
|
||
|
||
def run(self, args, cwd=None, env=None): | ||
|
||
""" | ||
Runs the action. | ||
|
||
:type args: list | ||
:param args: Command line arguments to pass to the binary | ||
|
||
:type cwd: str | ||
:param cwd: Directory where to execute the command (defaults to current dir) | ||
|
||
:rtype: str | ||
:return: text of the standard output from the command | ||
|
||
:raises aws_lambda_builders.workflows.go_dep.dep.ExecutionError: | ||
when the command executes with a non-zero return code. The exception will | ||
contain the text of the standard error output from the command. | ||
|
||
:raises ValueError: if arguments are not provided, or not a list | ||
""" | ||
|
||
if not isinstance(args, list): | ||
raise ValueError("args must be a list") | ||
|
||
if not args: | ||
raise ValueError("requires at least one arg") | ||
|
||
invoke_bin = [self.binary] + args | ||
|
||
LOG.debug("executing binary: %s", invoke_bin) | ||
|
||
p = self.osutils.popen(invoke_bin, | ||
stdout=self.osutils.pipe, | ||
stderr=self.osutils.pipe, | ||
cwd=cwd, | ||
env=env) | ||
|
||
out, err = p.communicate() | ||
|
||
if p.returncode != 0: | ||
raise ExecutionError(message=err) | ||
|
||
out = out.decode('utf-8') if isinstance(out, bytes) else out | ||
|
||
return out.strip() | ||
sthulb marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
""" | ||
Commonly used utilities | ||
""" | ||
|
||
import os | ||
import platform | ||
import tarfile | ||
import subprocess | ||
|
||
|
||
class OSUtils(object): | ||
|
||
""" | ||
Wrapper around file system functions, to make it easy to | ||
unit test actions in memory | ||
|
||
TODO: move to somewhere generic | ||
""" | ||
|
||
def joinpath(self, *args): | ||
return os.path.join(*args) | ||
|
||
def popen(self, command, stdout=None, stderr=None, env=None, cwd=None): | ||
p = subprocess.Popen(command, stdout=stdout, stderr=stderr, env=env, cwd=cwd) | ||
return p | ||
|
||
@property | ||
def pipe(self): | ||
return subprocess.PIPE | ||
|
||
@property | ||
def environ(self): | ||
return os.environ.copy() | ||
|
||
def dirname(self, path): | ||
return os.path.dirname(path) | ||
|
||
def abspath(self, path): | ||
return os.path.abspath(path) | ||
|
||
def is_windows(self): | ||
return platform.system().lower() == 'windows' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
""" | ||
Go Dep Workflow | ||
""" | ||
|
||
import logging | ||
import os | ||
|
||
from aws_lambda_builders.actions import CopySourceAction | ||
from aws_lambda_builders.workflow import BaseWorkflow, Capability | ||
|
||
from .actions import DepEnsureAction, GoBuildAction | ||
from .utils import OSUtils | ||
from .subproc_exec import SubprocessExec | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
class GoDepWorkflow(BaseWorkflow): | ||
""" | ||
A Lambda builder workflow that knows how to build | ||
Go projects using `dep` | ||
""" | ||
|
||
NAME = "GoDepBuilder" | ||
|
||
CAPABILITY = Capability(language="go", | ||
dependency_manager="dep", | ||
application_framework=None) | ||
|
||
EXCLUDED_FILES = (".aws-sam") | ||
|
||
def __init__(self, | ||
source_dir, | ||
artifacts_dir, | ||
scratch_dir, | ||
manifest_path, | ||
runtime=None, | ||
osutils=None, | ||
**kwargs): | ||
|
||
super(GoDepWorkflow, self).__init__(source_dir, | ||
artifacts_dir, | ||
scratch_dir, | ||
manifest_path, | ||
runtime=runtime, | ||
**kwargs) | ||
|
||
options = kwargs["options"] if "options" in kwargs else {} | ||
handler = options.get("handler", None) | ||
|
||
if osutils is None: | ||
osutils = OSUtils() | ||
|
||
# project base name, where the Gopkg.toml and vendor dir are. | ||
base_dir = osutils.abspath(osutils.dirname(manifest_path)) | ||
output_path = osutils.joinpath(osutils.abspath(artifacts_dir), handler) | ||
sthulb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
subprocess_dep = SubprocessExec(osutils, "dep") | ||
subprocess_go = SubprocessExec(osutils, "go") | ||
|
||
self.actions = [ | ||
sthulb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
DepEnsureAction(base_dir, subprocess_dep), | ||
GoBuildAction(base_dir, osutils.abspath(source_dir), output_path, subprocess_go, env=osutils.environ) | ||
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import os | ||
import shutil | ||
import sys | ||
import tempfile | ||
|
||
from unittest import TestCase | ||
|
||
from aws_lambda_builders.workflows.go_dep import utils | ||
|
||
|
||
class TestGoDepOSUtils(TestCase): | ||
|
||
def setUp(self): | ||
|
||
self.osutils = utils.OSUtils() | ||
|
||
def test_dirname_returns_directory_for_path(self): | ||
dirname = self.osutils.dirname(sys.executable) | ||
|
||
self.assertEqual(dirname, os.path.dirname(sys.executable)) | ||
|
||
def test_abspath_returns_absolute_path(self): | ||
|
||
result = self.osutils.abspath('.') | ||
|
||
self.assertTrue(os.path.isabs(result)) | ||
|
||
self.assertEqual(result, os.path.abspath('.')) | ||
|
||
def test_joinpath_joins_path_components(self): | ||
|
||
result = self.osutils.joinpath('a', 'b', 'c') | ||
|
||
self.assertEqual(result, os.path.join('a', 'b', 'c')) | ||
|
||
def test_popen_runs_a_process_and_returns_outcome(self): | ||
|
||
cwd_py = os.path.join(os.path.dirname(__file__), '..', '..', 'testdata', 'cwd.py') | ||
|
||
p = self.osutils.popen([sys.executable, cwd_py], | ||
stdout=self.osutils.pipe, | ||
stderr=self.osutils.pipe) | ||
|
||
out, err = p.communicate() | ||
|
||
self.assertEqual(p.returncode, 0) | ||
|
||
self.assertEqual(out.decode('utf8').strip(), os.getcwd()) | ||
|
||
def test_popen_can_accept_cwd(self): | ||
|
||
testdata_dir = os.path.join(os.path.dirname(__file__), '..', '..', 'testdata') | ||
|
||
p = self.osutils.popen([sys.executable, 'cwd.py'], | ||
stdout=self.osutils.pipe, | ||
stderr=self.osutils.pipe, | ||
cwd=testdata_dir) | ||
|
||
out, err = p.communicate() | ||
|
||
self.assertEqual(p.returncode, 0) | ||
|
||
self.assertEqual(out.decode('utf8').strip(), os.path.abspath(testdata_dir)) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.