Repository: aws/aws-sam-cli

Issue:
sam package of template with SAR metadata fails when using sam build
<!-- Make sure we don't have an existing Issue that reports the bug you are seeing (both open and closed). 
If you do find an existing Issue, re-open or add a comment to that Issue instead of creating a new one. -->

### Description

`sam package` fails, when trying to package artifacts built by `sam build`, if the template contains SAR metadata and references local files for `LicenseUrl` or `ReadmeUrl` which should get uploaded by `sam package`. Without using `sam build` that works properly, as the files are present in the template directory.

### Steps to reproduce

```
/tmp $ sam init
2019-01-14 13:44:20 Generating grammar tables from /usr/lib/python3.7/lib2to3/Grammar.txt
2019-01-14 13:44:20 Generating grammar tables from /usr/lib/python3.7/lib2to3/PatternGrammar.txt
[+] Initializing project structure...
[SUCCESS] - Read sam-app/README.md for further instructions on how to proceed
[*] Project initialization is now complete
/tmp $ cd sam-app/
```
* Insert minimal SAR-meta data into the template:
```
Metadata:
  AWS::ServerlessRepo::Application:
    Name: hello-world             
    Description: hello world
    Author: John
    SpdxLicenseId: MIT   
    LicenseUrl: ./LICENSE 
    SemanticVersion: 0.0.1
```
```
/tmp/sam-app $ echo "dummy license text" > LICENSE
/tmp/sam-app $ sam build --use-container
2019-01-14 13:45:23 Starting Build inside a container
2019-01-14 13:45:23 Found credentials in shared credentials file: ~/.aws/credentials
2019-01-14 13:45:23 Building resource 'HelloWorldFunction'

Fetching lambci/lambda:build-nodejs8.10 Docker container image......
2019-01-14 13:45:32 Mounting /tmp/sam-app/hello-world as /tmp/samcli/source:ro inside runtime container

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Package: sam package --s3-bucket <yourbucket>
    
'nodejs' runtime has not been validated!
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
/tmp/sam-app $ sam package --s3-bucket dummy

Unable to upload artifact ./LICENSE referenced by LicenseUrl parameter of AWS::ServerlessRepo::Application resource.
Parameter LicenseUrl of resource AWS::ServerlessRepo::Application refers to a file or folder that does not exist /tmp/sam-app/.aws-sam/build/LICENSE
```
### Observed result

`sam package` fails, because the `LICENSE` file isn't present in the build directory.

### Expected result

`sam package` succeeds.

### Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

1. OS: Debian/unstable
2. `sam --version`: `SAM CLI, version 0.10.0`


Discussion:

Resolving patch:
diff --git a/samcli/commands/_utils/template.py b/samcli/commands/_utils/template.py
--- a/samcli/commands/_utils/template.py
+++ b/samcli/commands/_utils/template.py
@@ -14,6 +14,10 @@
 from samcli.yamlhelper import yaml_parse, yaml_dump
 
 
+_METADATA_WITH_LOCAL_PATHS = {
+    "AWS::ServerlessRepo::Application": ["LicenseUrl", "ReadmeUrl"]
+}
+
 _RESOURCES_WITH_LOCAL_PATHS = {
     "AWS::Serverless::Function": ["CodeUri"],
     "AWS::Serverless::Api": ["DefinitionUri"],
@@ -132,6 +136,22 @@ def _update_relative_paths(template_dict,
 
     """
 
+    for resource_type, properties in template_dict.get("Metadata", {}).items():
+
+        if resource_type not in _METADATA_WITH_LOCAL_PATHS:
+            # Unknown resource. Skipping
+            continue
+
+        for path_prop_name in _METADATA_WITH_LOCAL_PATHS[resource_type]:
+            path = properties.get(path_prop_name)
+
+            updated_path = _resolve_relative_to(path, original_root, new_root)
+            if not updated_path:
+                # This path does not need to get updated
+                continue
+
+            properties[path_prop_name] = updated_path
+
     for _, resource in template_dict.get("Resources", {}).items():
         resource_type = resource.get("Type")
 


Test patch:
diff --git a/tests/unit/commands/_utils/test_template.py b/tests/unit/commands/_utils/test_template.py
--- a/tests/unit/commands/_utils/test_template.py
+++ b/tests/unit/commands/_utils/test_template.py
@@ -7,8 +7,8 @@
 from mock import patch, mock_open
 from parameterized import parameterized, param
 
-from samcli.commands._utils.template import get_template_data, _RESOURCES_WITH_LOCAL_PATHS, _update_relative_paths, \
-    move_template
+from samcli.commands._utils.template import get_template_data, _METADATA_WITH_LOCAL_PATHS, \
+     _RESOURCES_WITH_LOCAL_PATHS, _update_relative_paths, move_template
 
 
 class Test_get_template_data(TestCase):
@@ -78,10 +78,41 @@ def setUp(self):
 
         self.expected_result = os.path.join("..", "foo", "bar")
 
+    @parameterized.expand(
+        [(resource_type, props) for resource_type, props in _METADATA_WITH_LOCAL_PATHS.items()]
+    )
+    def test_must_update_relative_metadata_paths(self, resource_type, properties):
+
+        for propname in properties:
+            for path in [self.s3path, self.abspath, self.curpath]:
+                template_dict = {
+                    "Metadata": {
+                        resource_type: {
+                            propname: path
+                        },
+                        "AWS::Ec2::Instance": {
+                            propname: path
+                        }
+                    },
+                    "Parameters": {
+                        "a": "b"
+                    }
+                }
+
+                expected_template_dict = copy.deepcopy(template_dict)
+                if path == self.curpath:
+                    expected_template_dict["Metadata"][resource_type][propname] = \
+                        self.expected_result
+
+                result = _update_relative_paths(template_dict, self.src, self.dest)
+
+                self.maxDiff = None
+                self.assertEquals(result, expected_template_dict)
+
     @parameterized.expand(
         [(resource_type, props) for resource_type, props in _RESOURCES_WITH_LOCAL_PATHS.items()]
     )
-    def test_must_update_relative_paths(self, resource_type, properties):
+    def test_must_update_relative_resource_paths(self, resource_type, properties):
 
         for propname in properties: