kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Python の独自パッケージを作って AWS CodeArtifact で管理する

開発チームで共通的に使うコードを独自ライブラリ(パッケージ)にして管理したい場面はあると思う.今回 AWS CodeArtifact で管理する流れを試す❗AWS CodeArtifact は npm / pip / Maven など複数のパッケージマネージャーをサポートしているけど,今回は pip (Python) を前提にする.

aws.amazon.com

AWS CodeArtifact と AWS CDK

AWS CodeArtifact には大きく「ドメイン」「リポジトリ」という概念がある.詳しくは以下のドキュメントにまとまっている👌

docs.aws.amazon.com

AWS CDK で AWS CodeArtifact を設定する場合,AWS CloudFormation に沿った L1 ConstructCfnDomainCfnRepository を使う.設定次第ではあるけど,特に難しいところはないかなーと思う.

docs.aws.amazon.com

docs.aws.amazon.com

👾 sandbox-cdk-codeartifact-stack.ts

今回は AWS CodeArtifact に kakakakakku ドメインと sandbox-cdk-repository リポジトリを設定する.リポジトリにアップストリームリポジトリとして pypi-store (Python Packaging Authority) を設定すると外部のパブリックリポジトリとして透過的にパッケージを扱えるようになる.今回はプライベートなパッケージのみを AWS CodeArtifact で管理する形を試したく,アップストリームリポジトリは設定しなかった.

import {
  Stack,
  StackProps,
  aws_codeartifact,
} from 'aws-cdk-lib'
import { Construct } from 'constructs'

export class SandboxCdkCodeArtifactStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const domain = new aws_codeartifact.CfnDomain(this, 'SandboxCdkDomain', {
      domainName: 'kakakakakku'
    })

    new aws_codeartifact.CfnRepository(this, 'SandboxCdkRepository', {
      domainName: domain.domainName,
      repositoryName: 'sandbox-cdk-repository',
    })
  }
}

独自パッケージをパッケージングする

まずは以下の Python Packaging User Guide を参考にサンプルパッケージを実装する.今回はドキュメントに沿って example_package_kakakakakku という名前にした.

packaging.python.org

コード的には数値を +1 する add_one() 関数を追加している👌

def add_one(number):
    return number + 1

最終的に以下のようなディレクトリ階層になった.

$ tree . -a -I dist
.
├── .gitignore
├── LICENSE
├── README.md
├── pyproject.toml
└── src
    └── example_package_kakakakakku
        ├── __init__.py
        └── example.py

検証中に出たエラーも残しておく💨

ERROR 'example_package_kakakakakku-0.0.1/.gitignore' is a link to an absolute path
ERROR Backend subprocess exited when trying to invoke build_wheel

うまくパッケージングもできた❗

$ python3 -m build
(中略)
Successfully built example_package_kakakakakku-0.0.1.tar.gz and example_package_kakakakakku-0.0.1-py3-none-any.whl

$ ls -1 dist
example_package_kakakakakku-0.0.1-py3-none-any.whl
example_package_kakakakakku-0.0.1.tar.gz

パッケージを AWS CodeArtifact にアップロードする

ドキュメントに書いてある通り,パッケージを AWS CodeArtifact にアップロードする場合は twine を使う.

docs.aws.amazon.com

aws codeartifact login --tool twine コマンドを使って認証トークンを取得しつつ,twine upload --repository codeartifact コマンドでパッケージをアップロードする.

$ aws codeartifact login --tool twine --domain kakakakakku --repository sandbox-cdk-repository --region ap-northeast-1
$ twine upload --repository codeartifact dist/*

AWS CodeArtifact にアップロードできた

パッケージを使う

今度は AWS CodeArtifact にアップロードしたパッケージを使ったコードを実装する.ちなみに Python を Homebrew でインストールしていると aws codeartifact login --tool pip コマンドを実行したときに pip was not found. Please verify installation. というエラーが出てしまうという既知の問題がある.venv を使うと回避できるため今回は venv で仮想環境を作る.あとは普通に pip install コマンドで example-package-kakakakakku を取得する.

$ python -m venv venv
$ source venv/bin/activate

(venv) $ aws codeartifact login --tool pip --domain kakakakakku --repository sandbox-cdk-repository --region ap-northeast-1
(venv) $ pip install example-package-kakakakakku
Successfully installed example-package-kakakakakku-0.0.1

(venv) $ pip list
Package                     Version
--------------------------- -------
example_package_kakakakakku 0.0.1
pip                         23.3.1
setuptools                  69.0.2

そして以下のような main.py を実行するとうまく実行できる👏

👾 main.py

from example_package_kakakakakku import example

print(example.add_one(1))
print(example.add_one(2))
print(example.add_one(3))

注意点

今回は AWS CodeArtifact リポジトリにアップストリームリポジトリを設定しなかったため,例えば requests のような一般的なパッケージをインストールしようとするとエラーになってしまう💨

(venv) $ pip install requests
Looking in indexes: https://aws:****@kakakakakku-000000000000.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/sandbox-cdk-repository/simple/
ERROR: Could not find a version that satisfies the requirement requests (from versions: none)
ERROR: No matching distribution found for requests

以下のドキュメントに載っている通り,pip コマンドの -i / --index-url オプションを使って pypi を明示的に指定するとインストールできるようになる.ただし正直これだと使いにくく感じるため,アップストリームリポジトリを設定すると良いのかなぁー \( 'ω')/ コストとのトレードオフになりそう.

$ pip install --index-url https://pypi.org/simple requests

docs.aws.amazon.com

あと AWS CodeArtifact の認証回りでうまく pip コマンドを実行できなくなったら以下の2ファイルを確認しつつ,削除してみると改善するかも💡

$ rm ~/.config/pip/pip.conf
$ rm ~/.pypirc

今回はここまで❗️

実は今まで AWS CodeArtifact は試したことがなくて勉強になった〜 \( 'ω')/