繁体   English   中英

如何使用 Poetry 将 Python 包发布到 CodeArtifact?

[英]How can I publish Python packages to CodeArtifact using Poetry?

尝试将诗歌 package 发布到 AWS CodeArtifact。 它支持pip这应该表明它也支持poetry ,因为poetry可以上传到 PyPi 服务器。

我已经像这样配置了域:

export CODEARTIFACT_AUTH_TOKEN=`aws codeartifact get-authorization-token --domain XXXX --domain-owner XXXXXXXXXXXX --query authorizationToken --output text`
poetry config repositories.the_aws_repo https://aws:$CODEARTIFACT_AUTH_TOKEN@XXXX-XXXXXXXXXXXX.d.codeartifact.eu-central-1.amazonaws.com/pypi/XXXX/simple/
poetry config pypi-token.the_aws_repo $CODEARTIFACT_AUTH_TOKEN

但是我在尝试发布 package 时收到 404:

❯ poetry publish --repository the_aws_repo -vvv

No suitable keyring backend found
No suitable keyring backends were found
Using a plaintext file to store and retrieve credentials
Publishing xxx (0.1.5) to the_aws_repo
 - Uploading xxx-0.1.5-py3-none-any.whl 100%

  Stack trace:

  7  ~/.poetry/lib/poetry/_vendor/py3.8/clikit/console_application.py:131 in run
      129│             parsed_args = resolved_command.args
      130│
    → 131│             status_code = command.handle(parsed_args, io)
      132│         except KeyboardInterrupt:
      133│             status_code = 1

  6  ~/.poetry/lib/poetry/_vendor/py3.8/clikit/api/command/command.py:120 in handle
      118│     def handle(self, args, io):  # type: (Args, IO) -> int
      119│         try:
    → 120│             status_code = self._do_handle(args, io)
      121│         except KeyboardInterrupt:
      122│             if io.is_debug():

  5  ~/.poetry/lib/poetry/_vendor/py3.8/clikit/api/command/command.py:171 in _do_handle
      169│         handler_method = self._config.handler_method
      170│
    → 171│         return getattr(handler, handler_method)(args, io, self)
      172│
      173│     def __repr__(self):  # type: () -> str

  4  ~/.poetry/lib/poetry/_vendor/py3.8/cleo/commands/command.py:92 in wrap_handle
       90│         self._command = command
       91│
    →  92│         return self.handle()
       93│
       94│     def handle(self):  # type: () -> Optional[int]

  3  ~/.poetry/lib/poetry/console/commands/publish.py:77 in handle
      75│         )
      76│
    → 77│         publisher.publish(
      78│             self.option("repository"),
      79│             self.option("username"),

  2  ~/.poetry/lib/poetry/publishing/publisher.py:93 in publish
      91│         )
      92│
    → 93│         self._uploader.upload(
      94│             url,
      95│             cert=cert or get_cert(self._poetry.config, repository_name),

  1  ~/.poetry/lib/poetry/publishing/uploader.py:119 in upload
      117│
      118│         try:
    → 119│             self._upload(session, url, dry_run)
      120│         finally:
      121│             session.close()

  UploadError

  HTTP Error 404: Not Found

  at ~/.poetry/lib/poetry/publishing/uploader.py:216 in _upload
      212│                     self._register(session, url)
      213│                 except HTTPError as e:
      214│                     raise UploadError(e)
      215│
    → 216│             raise UploadError(e)
      217│
      218│     def _do_upload(
      219│         self, session, url, dry_run=False
      220│     ):  # type: (requests.Session, str, Optional[bool]) -> None

我的 AWS IAM 用户有权执行此操作,因为我在存储库中授予了它相关权限。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXXXX:user/ShayN"
            },
            "Action": [
                "codeartifact:AssociateExternalConnection",
                "codeartifact:CopyPackageVersions",
                "codeartifact:DeletePackageVersions",
                "codeartifact:DeleteRepository",
                "codeartifact:DeleteRepositoryPermissionsPolicy",
                "codeartifact:DescribePackageVersion",
                "codeartifact:DescribeRepository",
                "codeartifact:DisassociateExternalConnection",
                "codeartifact:DisposePackageVersions",
                "codeartifact:GetPackageVersionReadme",
                "codeartifact:GetRepositoryEndpoint",
                "codeartifact:ListPackageVersionAssets",
                "codeartifact:ListPackageVersionDependencies",
                "codeartifact:ListPackageVersions",
                "codeartifact:ListPackages",
                "codeartifact:PublishPackageVersion",
                "codeartifact:PutPackageMetadata",
                "codeartifact:PutRepositoryPermissionsPolicy",
                "codeartifact:ReadFromRepository",
                "codeartifact:UpdatePackageVersionsStatus",
                "codeartifact:UpdateRepository"
            ],
            "Resource": "*"
        }
    ]
}

我错过了什么?

问题是回购 url 末尾的/simple/ 此部分仅应在从该存储库中提取时添加,而不是在发布到它时添加。 如果您仔细查看AWS CodeArtifact关于如何使用twine发布的文档,您会发现它也不存在。

这有效:

# This will give the repo url without the /simple/ part
# Example: https://<my-domain>-<domain-owner-id>.d.codeartifact.<region>.amazonaws.com/pypi/<my-repo>/
# Note the lack of the "aws:auth-token@" part
export CODEARTIFACT_REPOSITORY_URL=`aws codeartifact get-repository-endpoint --domain my-domain --domain-owner domain-owner-id --repository my-repo --format pypi --query repositoryEndpoint --output text`

# This will give the token to access the repo
export CODEARTIFACT_AUTH_TOKEN=`aws codeartifact get-authorization-token --domain my-domain --domain-owner domain-owner-id --query authorizationToken --output text`

# This specifies the user who accesses the repo
export CODEARTIFACT_USER=aws

# Now use all of these when configuring the repo in poetry
poetry config repositories.<my-repo-name-for-poetry> $CODEARTIFACT_REPOSITORY_URL
poetry config http-basic.<my-repo-name-for-poetry> $CODEARTIFACT_USER $CODEARTIFACT_AUTH_TOKEN

请注意,当您的 AWS 登录 session 结束时,身份验证令牌将过期。 因此,您必须在每次过期时使用新令牌设置http-basic.<my-repo-name-for-poetry>

仅供参考,我遇到了同样的问题,我花了几个小时才弄清楚。 但最后,更仔细地阅读文档应该对我有所帮助。

这个 Python 脚本可以配置 pip、poetry 和 twine 来与你的神器一起工作。 运行例如

python ./codeartifact_login.py configure --tool poetry
poetry publish --repository your-artifactory
#!/usr/bin/env python
import os

import boto3
import fire


class CodeArtifact(object):

    @staticmethod
    def run(cmd: str):
        print(os.popen(cmd=cmd).read())

    @staticmethod
    def configure(tool: str = "twine"):
        if tool not in ["twine", "pip", "poetry"]:
            raise RuntimeError(f"Not recognise tool: {tool}")
        domain = "your-artifactory"
        repo = "your-repo"
        account_id = boto3.client('sts').get_caller_identity().get('Account')
        region = boto3.session.Session().region_name
        if tool == "poetry":
            CODEARTIFACT_REPOSITORY_URL = f"https://{domain}-{account_id}.d.codeartifact.{region}.amazonaws.com/pypi/{repo}/"
            CodeArtifact.run(cmd=f"poetry config repositories.{domain} {CODEARTIFACT_REPOSITORY_URL}")
            CODEARTIFACT_AUTH_TOKEN = boto3.client('codeartifact').get_authorization_token(
                domain=domain,
                domainOwner=account_id,
                durationSeconds=12 * 3600
            )["authorizationToken"]
            CodeArtifact.run(cmd=f"poetry config http-basic.{domain} aws {CODEARTIFACT_AUTH_TOKEN}")
        else:
            CodeArtifact.run(
                cmd=f"aws codeartifact login --tool {tool} --domain {domain} --domain-owner {account_id} --repository {repo}")


if __name__ == '__main__':
    fire.Fire(CodeArtifact)  # configure(tool="poetry")

参考:

编辑:查看接受的答案,它有效!

如果有人从谷歌搜索到这里,根据我写这篇文章时的情况(2020 年 12 月 19 日):

poetry中没有对此的内置支持。 您可以使用它从 AWS CodeArtifact 安装,但不能上传,除非您可以将机密放入pyproject.toml文件(使用令牌更新 URL)。 我的解决方法是使用twine上传(只需遵循 AWS 的指南)并使用poetry进行安装(需要添加一个poetry.toml文件并将 CodeArtifact 添加为pyproject.toml中的源)。

相关 GitHub 问题。 .

对于任何试图让Poetry在 Windows Powershell上运行的人,您可以使用环境变量来使事情正常运行。 由于 windows 命令无法处理长 AWS 身份验证令牌,因此它仅在您使用环境变量时才有效。

希望这些步骤和命令示例对您有所帮助:

私有存储库配置 (Windows)

将包推送到“myprivaterepo”

1. 登录 AWS 或配置 AWS CLI

    $Env:AWS_ACCESS_KEY_ID={{ awsaccesskeyidhere }}
    $Env:AWS_SECRET_ACCESS_KEY={{ secretaccesskeyhere }}
    $Env:AWS_SESSION_TOKEN={{ abcdefghijklmnopqrstuvwxyz }}

2. 获取 CodeArtifact 身份验证令牌

    $Env:CODEARTIFACT_AUTH_TOKEN=aws --region us-east-1 codeartifact get-authorization-token --domain {{ repo_domain }} --domain-owner {{ aws_account }} --query authorizationToken --output text

您可以通过运行echo $Env:CODEARTIFACT_AUTH_TOKEN检查这是否有效。 如果它有效,您将看到一长串文本。 还要确保 AWS 区域是您实际使用的区域。

3.设置诗歌环境变量

这部分对我来说并不那么明显。 这里的关键是在环境变量名称中使用存储库的大写名称,并且在下一步中它也应该是相同的名称。 诗歌文档中有关使用环境变量的更多信息。

    $Env:POETRY_HTTP_BASIC_MYPRIVATEREPO_USERNAME=echo aws
    $Env:POETRY_HTTP_BASIC_MYPRIVATEREPO_PASSWORD=$Env:CODEARTIFACT_AUTH_TOKEN

另一个例子,如果你的仓库被命名为“ secretprojectrepo ”,你可以使用: $Env:POETRY_HTTP_BASIC_SECRETPROJECTREPO_USERNAME=echo aws

4.配置诗歌

此处的存储库名称应为小写。 请注意 URL 末尾不包含“/simple”。 如果您从 AWS 控制台复制它,则需要将其删除,因为 Poetry 没有使用该协议进行上传。

    poetry config repositories.myprivaterepo https://myprivaterepo-1234567890.d.codeartifact.us-east-1.amazonaws.com/pypi/myprivaterepo

注意:当您在 AWS 控制台中查看连接说明时,您可以从“手动设置”说明中获取 URL。 应该是格式https://aws:$CODEARTIFACT_AUTH_TOKEN@myprivaterepo-1234567890.d.codeartifact.us-east-1.amazonaws.com/pypi/myprivaterepo/simple/ 只需从 URL 中删除凭据部分“aws:$CODEARTIFACT_AUTH_TOKEN@”,因为我们使用环境变量向 Poetry 提供身份验证信息。

手动配置是第二个选项

5. 构建和发布

    poetry build
    poetry publish -r myprivaterepo

从私有存储库安装依赖项

要设置从存储库中提取,请按照上述步骤登录 AWS 并配置 Poetry。 接下来,您将需要pyproject.toml中的一个部分,该部分向 Poetry 指示要用作源的存储库。 附加信息: 诗歌文档

6. 配置 Poetry 的源代码库

    [[tool.poetry.source]]
    name = "myprivaterepo"
    url = "https://myprivaterepo-1234567890.d.codeartifact.us-east-1.amazonaws.com/pypi/myprivaterepo/simple/"
    default = true

两个重要说明:

  1. 这是与前面步骤相同的存储库 URL,但要提取包,您需要 URL 末尾的“ /simple/ ”。
  2. 默认部分是可选的。 默认为 true 时,Poetry 不会尝试在 PyPi 中查找包。 关闭时,它还将搜索 PyPi。 您还可以选择将您的私有存储库设置为辅助源。

诗歌文档:禁用 PyPi

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM