【问题标题】:Building from and uploading to a local Python repository without writing credentials to disk从本地 Python 存储库构建并上传到本地 Python 存储库,而无需将凭据写入磁盘
【发布时间】:2017-11-14 18:01:35
【问题描述】:

我设置了一个 Python 构建管道,其中一个 Jfrog Artifactory Python 存储库为我们的内部包提供服务。

管道使用此存储库来解决内部依赖关系并上传构建工件。

目前这是通过python setup.py bdist_wheel sdist upload -r local 完成的。此命令实际上要求凭据在磁盘上两次;一次用于通过 ~/.pydistutils.cfg 解决本地依赖关系:

[easy_install]
index_url=https://username:password@artifactory/api/repo/path/simple

...再次在 ~/.pypirc 中上传构建包:

[distutils]
index-servers = local

[local]
repository: https://artifactory/api/repo/path
username: build_agent
password: ****

出于安全原因,我希望用户名和密码永远不要接触磁盘。我们已经有了一种从 (Hashicorp) Vault 将机密注入构建环境的安全方法,我想利用它来获取 Artifactory 凭据。

但是,虽然我可以设置 PIP_INDEX_URL 以使用 pip 安装软件包,但我可以看到 setuptools 没有等效项。如果没有定义这些文件,python setup.py sdist 命令会导致堆栈跟踪出现以下错误:

distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('local-package==0.0.3')

显然,它试图解决对公共 pypi 的本地依赖,这出于多种原因是不可取的(本地存储库代理 pypi,因此我们不应该阅读公共 pypi 以防止劫持)。

基本上我的问题是; 如何使用环境变量中而不是 ~/.pypirc 或 ~/.pydistutils.cfg 中的凭据构建和上传在本地存储库中具有依赖关系的 python 包到该本地存储库?强>

附加背景

原始实现在使用 Packer 构建的构建代理 AMI 中烘焙了 .pypirc 和 .pydistutils.cfg。

这样做的问题在于,存储库的用户名和密码基本上可以以纯文本形式被任何有权访问 AWS 账户并能够使用图像下载或创建新实例的人读取。

这很简单,只需在开始构建之前添加一个构建步骤即可设置 pypirc!我想避免这种方法,因为它在创建全局运行时构建依赖项的意义上是脆弱的。将来,有人可以假设已经创建了配置文件而不自己创建了一个作业,并且它几乎总是可以工作,因为另一个作业首先运行。我无法在每次构建后删除该文件,因为可能存在需要该文件存在的并发构建。

【问题讨论】:

    标签: python artifactory setuptools


    【解决方案1】:

    我找到了一个解决方案,但不是特别漂亮。

    第一个问题是setup_requires。因为它在进程的早期调用easy_install,所以很难覆盖;甚至创建 Distribution 子类并覆盖 fetch_egg 方法也无济于事。我现在确定的解决方法是包装设置方法并通过 pip 预安装它们(使用PIP_INDEX_URL 设置):

    from setuptools import setup
    
    def _setup(**kwargs):
        requires = kwargs.get('setup_requires') or []
    
        for req in requires:
            pip.main(['install', req])
    
        return setup(**kwargs)
    
    
    _setup(
        name='mypackage',
        ...
    )
    

    只有在 setup_requires 中指定本地依赖项的包才需要,python setup.py install 仍然损坏。由于 pip 在 tox 中进行安装([testenv] 部分中的deps = .[test])并且从不使用 setup.py 进行安装,因此损坏的安装命令不是问题。

    第二个问题是上传。我没有使用 setup.py upload 进行上传,而是将此任务转移到 twine。最新版本的 twine 从环境中读取 TWINE_USERNAME、TWINE_PASSWORD 和 TWINE_REPOSITORY_URL(如果它们不在传统配置文件中)。

    无论如何,我很想为第一个问题找到一个更优雅的解决方案,尤其是没有让 setup.py install 损坏的解决方案,但现在就可以了。

    【讨论】:

    • 您是否设法让 twine 与 Artifactory Python 存储库一起工作?出于同样的原因,我想使用它,但 Artifactory 拒绝了我使用 HTTP 400 和消息 "No enum constant org.jfrog.repomd.pypi.model.PypiMetadata.MetadataVersion.v2_1" 的推送
    • 是的,麻绳对我来说很好用。您描述的问题听起来像 Artifactory 不支持您上传的包的元数据。确保您运行的是最新版本的 Artifactory;否则,您将不得不找到一种方法来构建具有较旧元数据格式的软件包(我通过降级 setuptools IIRC 实现了这一点)。此票证引用了旧格式的问题:jfrog.com/jira/browse/RTFACT-12710
    • 谢谢。我在 Artifactory 6.6 上,所以不是最新的,但不是古老的。固定setuptools<38.5.2 实际上可以解决问题,似乎 38.5.2 及更高版本将使用元数据 2.1。你在哪个设置工具上?如果您是最近的并且它正在工作,那么它必须在 Artifactory 中修复,但我在票证或发行说明中找不到提及。在不明确知道此问题是否已修复的情况下,可能很难证明升级实例的合理性。
    • 自从我上次看这个已经大约一年了,但结果我固定在完全相同的 setuptools 版本 38.5.2 上。我们使用 SaaS 版本的 artifactory,所以它会自动更新。
    • 啊,那说明了。我认为这是我们目前最好的选择。
    猜你喜欢
    • 2014-03-23
    • 2017-05-16
    • 2011-07-23
    • 1970-01-01
    • 2023-03-09
    • 2020-09-11
    • 2018-03-11
    • 2013-12-17
    • 1970-01-01
    相关资源
    最近更新 更多