如何使用 Poetry 将 Python 包发布到 CodeArtifact?
How can I publish Python packages to CodeArtifact using Poetry?
正在尝试将 Poetry 包发布到 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
但是我在尝试发布包时收到 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": "*"
}
]
}
我错过了什么?
编辑:查看已接受的答案,有效!
如果有人通过 Google 搜索来到这里,根据我撰写本文时的情况(2020 年 12 月 19 日):
poetry
中没有对此的内置支持。您可以使用它从 AWS CodeArtifact 安装,但不能上传,除非您同意将秘密放入 pyproject.toml
文件(使用令牌更新 URL)。我的解决方法是使用 twine
上传(只需遵循 AWS 的指南)并使用 poetry
安装(需要添加 poetry.toml
文件并将 CodeArtifact 添加为 pyproject.toml
中的源).
问题出在回购 url 末尾的 /simple/
。这部分应该只在从该 repo 中提取时添加,而不是在发布到它时添加。如果您仔细查看有关如何使用 twine
发布的 documentation of AWS CodeArtifact,您会发现它也不在那里。
这个有效:
# 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 登录会话结束时过期。因此,您必须在每次过期时使用新令牌设置 http-basic.<my-repo-name-for-poetry>
。
仅供参考,我遇到了同样的问题,我花了好几个小时才弄明白。但最终,更仔细地阅读文档应该对我有所帮助。
对于任何试图在 Windows Powershell 上获取 Poetry 运行 的人,您可以使用环境变量来获取事情正常。由于 windows 命令无法处理长 AWS 身份验证令牌,因此它仅在您使用环境变量时有效。
希望这些步骤和命令示例对您有所帮助:
私有存储库配置(Windows)
正在将包推送到“myprivaterepo”
1。登录 AWS 或 configure 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。设置 Poetry 环境变量
这部分对我来说不是很明显。这里的关键是在环境变量名称中使用您存储库的大写名称,并且在下一步中也应该是相同的名称。诗歌中的更多信息 documentation for using environment variables.
$Env:POETRY_HTTP_BASIC_MYPRIVATEREPO_USERNAME=echo aws
$Env:POETRY_HTTP_BASIC_MYPRIVATEREPO_PASSWORD=$Env:CODEARTIFACT_AUTH_TOKEN
再举一个例子,如果你的 repo 被命名为“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 指示要将哪个存储库用作源。附加信息:Poetry Documentation
6.配置 Poetry 的源存储库
[[tool.poetry.source]]
name = "myprivaterepo"
url = "https://myprivaterepo-1234567890.d.codeartifact.us-east-1.amazonaws.com/pypi/myprivaterepo/simple/"
default = true
两个重要说明:
- 这是前面步骤中的同一个存储库 URL,但是要拉取包,您需要最后的“/simple/” URL.
- 默认部分是可选的。当默认为 true 时,Poetry 不会尝试查看 PyPi 中的包。停止时,它还会搜索 PyPi。您还可以选择将您的私人存储库设置为次要来源。
此 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")
参考文献:
正在尝试将 Poetry 包发布到 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
但是我在尝试发布包时收到 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": "*"
}
]
}
我错过了什么?
编辑:查看已接受的答案,有效!
如果有人通过 Google 搜索来到这里,根据我撰写本文时的情况(2020 年 12 月 19 日):
poetry
中没有对此的内置支持。您可以使用它从 AWS CodeArtifact 安装,但不能上传,除非您同意将秘密放入 pyproject.toml
文件(使用令牌更新 URL)。我的解决方法是使用 twine
上传(只需遵循 AWS 的指南)并使用 poetry
安装(需要添加 poetry.toml
文件并将 CodeArtifact 添加为 pyproject.toml
中的源).
问题出在回购 url 末尾的 /simple/
。这部分应该只在从该 repo 中提取时添加,而不是在发布到它时添加。如果您仔细查看有关如何使用 twine
发布的 documentation of AWS CodeArtifact,您会发现它也不在那里。
这个有效:
# 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 登录会话结束时过期。因此,您必须在每次过期时使用新令牌设置 http-basic.<my-repo-name-for-poetry>
。
仅供参考,我遇到了同样的问题,我花了好几个小时才弄明白。但最终,更仔细地阅读文档应该对我有所帮助。
对于任何试图在 Windows Powershell 上获取 Poetry 运行 的人,您可以使用环境变量来获取事情正常。由于 windows 命令无法处理长 AWS 身份验证令牌,因此它仅在您使用环境变量时有效。
希望这些步骤和命令示例对您有所帮助:
私有存储库配置(Windows)
正在将包推送到“myprivaterepo”
1。登录 AWS 或 configure 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。设置 Poetry 环境变量
这部分对我来说不是很明显。这里的关键是在环境变量名称中使用您存储库的大写名称,并且在下一步中也应该是相同的名称。诗歌中的更多信息 documentation for using environment variables.
$Env:POETRY_HTTP_BASIC_MYPRIVATEREPO_USERNAME=echo aws
$Env:POETRY_HTTP_BASIC_MYPRIVATEREPO_PASSWORD=$Env:CODEARTIFACT_AUTH_TOKEN
再举一个例子,如果你的 repo 被命名为“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 指示要将哪个存储库用作源。附加信息:Poetry Documentation
6.配置 Poetry 的源存储库
[[tool.poetry.source]]
name = "myprivaterepo"
url = "https://myprivaterepo-1234567890.d.codeartifact.us-east-1.amazonaws.com/pypi/myprivaterepo/simple/"
default = true
两个重要说明:
- 这是前面步骤中的同一个存储库 URL,但是要拉取包,您需要最后的“/simple/” URL.
- 默认部分是可选的。当默认为 true 时,Poetry 不会尝试查看 PyPi 中的包。停止时,它还会搜索 PyPi。您还可以选择将您的私人存储库设置为次要来源。
此 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")
参考文献: