CodeCommit API의 CreateCommit의 움직임이 가정과 다른 이야기

개요



Lambda (python)로 작성한 파일을 CodeCommit API (CreateCommit)를 사용하여 리포지토리에 추가 (업데이트)하려고했지만 잘하지 못하고 조사하면 API 사양이 자신의 가정과 다르므로 비망록으로 그 때의 내용을 정리한다.

하고 싶었던 일



S3에 있는 파일을 Lambda에서 편집하여 편집한 파일을 CodeCommit 리포지토리에 추가(업데이트)한다.

만든 Lambda 함수


s3 = boto3.resource('s3')
cc = boto3.client('codecommit')

def lambda_handler(event, context):
    bucket = s3.Bucket('<バケット名>')
    obj = bucket.Object('<オブジェクト名>')
    res_obj = obj.get()    
    body= res_obj['Body'].read()

    〜〜〜(編集処理)〜〜〜

    res_branch = cc.get_branch(repositoryName='<リポジトリ名>',branchName='<ブランチ名>')
    commit_id = res_branch['branch']['commitId']

    for (root, folders, files) in os.walk('/tmp/'):
        for file in files:
            file_path = os.path.join(root, file)
            putfile_entry = {'filePath': str(file_path).replace('/tmp/', 'piyo/'),
                            'sourceFile': {'filePath': file_path}}
            putfile_list.append(putfile_entry)

    return cc.create_commit(repositoryName='<リポジトリ名>', branchName='<ブランチ名>', parentCommitId=commit_id, putFiles=putfile_list)

이때 예상한 동작


putFiles -> sourceFile -> filePath 로 지정한 로컬 파일 (이 경우는 Lambda 상의 파일)을 putFiles -> filePath 로 지정한 리포지토리내의 패스에 추가한다고 생각하고 있었다.

실행 결과


[ERROR] FileDoesNotExistException: An error occurred (FileDoesNotExistException) when calling the CreateCommit operation: The file cannot be copied or moved because no file with that name exists in the specified path. Make sure that the file name is correct, and verify whether the file still exists. The file might have been moved or deleted by a previous commit. Source file path: tmp/piyo01.json
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 102, in lambda_handler
    return cc.create_commit(repositoryName=repo_name, branchName=branch_name, parentCommitId=commit_id, putFiles=putfile_list)
  File "/var/runtime/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/var/runtime/botocore/client.py", line 676, in _make_api_call
    raise error_class(parsed_response, operation_name)END RequestId: e8c03049-767c-41e8-9d3a-833f1d820a5c

그런 소스 파일이 존재하지 않는 오류. . .

조사(1)


create_commit에 지정된 매개 변수를 확인하십시오.
create_commitputFiles 에 지정한 값은 다음과 같다.
[{'filePath': 'piyo/piyo01.json', 'sourceFile': {'filePath': '/tmp/piyo01.json'}}]

Lambda의/tmp 디렉토리에 출력 된 파일이 소스 파일에 지정되었지만 FileDoesNotExistException가 발생했습니다.

에러 메세지를 잘 보면, 소스 파일의 패스의 선두의 슬래시(/)가 없어지고 있다. 왜?
Source file path: tmp/piyo01.json

왜?

조사(2)


create_commit 의 문서를 확인한다.

putFiles의 파라미터 설명





(sourceFile 설명을 Google 번역)



거친 설명으로 잘 모르겠습니다. . .

조사(3)



CodeCommit 문서를 확인합니다.


file1.py 및 file2.py라는 파일을 변경하는 커밋을 만들려면 파일의 이름을 picture.png에서 image1.png로 변경하고 pictures라는 디렉토리에서 images라는 디렉토리 로 이동하여 최신 커밋 ID가 4c925148EXAMPLE인 MyFeatureBranch라는 지점의 MyDemoRepo라는 리포지토리에 있는 ExampleSolution.py라는 파일을 삭제합니다.
aws codecommit create-commit --repository-name MyDemoRepo --branch-name MyFeatureBranch --parent-commit-id 4c925148EXAMPLE --name "Saanvi Sarkar"
 --email "[email protected]" --commit-message "I'm creating this commit to update a variable name in a number of files."
 --keep-empty-folders false  --put-files '{"filePath": "file1.py", "fileMode": "EXECUTABLE", "fileContent": "bucket_name = sys.argv[1] region = sys.argv[2]"}'
'{"filePath": "file2.txt", "fileMode": "NORMAL", "fileContent": "//Adding a comment to explain the variable changes in file1.py"}' '{"filePath": "images/image1.png",
"fileMode": "NORMAL", "sourceFile": {"filePath": "pictures/picture.png", "isMove": true}}' --delete-files filePath="ExampleSolution.py"
ファイルの名前を picture.png から image1.png に変更し、それを pictures という名前のディレクトリから images という名前のディレクトリに移動'{"filePath": "images/image1.png","fileMode": "NORMAL", "sourceFile": {"filePath": "pictures/picture.png", "isMove": true}}'
응? sourceFile 리포지토리의 파일 경로를 지정하고 있습니까?

awscli로 동작 확인


$ tree <リポジトリ名>/
<リポジトリ名>/
├── fuga
│   └── piyo.txt
└── hoge.txt

1 directory, 2 files
$ cat <リポジトリ名>/hoge.txt
hoge

파일의 이름을 hoge.txt에서 hogera.txt로 바꾸고 fuga라는 디렉토리로 변경하십시오.
$ aws codecommit create-commit \
> --repository-name <リポジトリ名> \
> --branch-name <ブランチ名> \
> --parent-commit-id <親コミットID> \
> --put-files '[{"filePath": "fuga/hogera.txt", "sourceFile": {"filePath": "hoge.txt", "isMove": true}}]'
{
    "commitId": "bf2084b422d8c120bdb0771ce1808d269dd0ee31",
    "treeId": "8176bcf69b9423bb79a29044a984fc0452cf6a0b",
    "filesAdded": [
        {
            "absolutePath": "fuga/hogera.txt",
            "blobId": "2262de0c121f22df8e78f5a37d6e114fd322c0b0",
            "fileMode": "NORMAL"
        }
    ],
    "filesUpdated": [],
    "filesDeleted": [
        {
            "absolutePath": "hoge.txt",
            "blobId": "2262de0c121f22df8e78f5a37d6e114fd322c0b0",
            "fileMode": "NORMAL"
        }
    ]
}

로컬 브랜치를 원격 브랜치와 동기화한 후,
$ git pull

파일을 확인하면
$ tree <リポジトリ名>/
<リポジトリ名>/
└── fuga
    ├── hogera.txt
    └── piyo.txt

1 directory, 2 files
$ cat <リポジトリ名>/fuga/hogera.txt 
hoge

hoge.txt가 hogera.txt로 이름이 바뀌고 fuga 디렉토리로 이동되었음을 확인했습니다.

즉, putFiles -> sourceFile -> filePath 에는, 로컬의 파일이 아니고, 리포지토리내의 파일을 지정하는 사양이다.

그래서 오류 메시지에 표시된 소스 파일의 경로 ( tmp/piyo01.json )에는 슬래시 (/)가 없어졌습니다.
※리포지토리내의 루트 디렉토리로부터의 상대 패스가 되어 있다.

회피 방법



로컬의 파일을 CodeCommit 리포지터리에 추가(갱신)하는 방법으로서, sourceFile 는 아니고, fileContent 로 컨텐츠의 내용을 직접 지정하는 방법으로 바꾸면, 커밋할 수 있었다.
    for (root, folders, files) in os.walk('/tmp/'):
        for file in files:
            file_path = os.path.join(root, file)
            with open(file_path, mode='r+b') as file_obj:
                file_content = file_obj.read()
            putfile_entry = {'filePath': str(file_path).replace('/tmp/', 'piyo/'),
                            'fileContent': file_content}
            putfile_list.append(putfile_entry)

    return cc.create_commit(repositoryName='<リポジトリ名>', branchName='<ブランチ名>', parentCommitId=commit_id, putFiles=putfile_list)

다만, 상기 코드는/tmp 디렉토리 부하의 모든 파일을 갱신하기 위해(때문에), 모든 파일로 어떠한 변경되고 있을 필요가 있다.

변경되지 않은 파일이 있으면 다음 오류가 발생합니다.
[ERROR] SamePathRequestException: An error occurred (SamePathRequestException) when calling the CreateCommit operation: Cannot put the file at the specified path because there are one or more conflicting file change requests for that file. Either resolve the conflicts locally, or put the files you want to add in different paths, and then try again.. Path: piyo/piyo01.json
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 103, in lambda_handler
    return cc.create_commit(repositoryName=repo_name, branchName=branch_name, parentCommitId=commit_id, putFiles=putfile_list)
  File "/var/runtime/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/var/runtime/botocore/client.py", line 676, in _make_api_call
    raise error_class(parsed_response, operation_name)END RequestId: b16063f3-e356-4117-95fb-a087ce0c8401

좋은 웹페이지 즐겨찾기