这可能是一个经常出现的问题,但我找不到一种可靠的方法来在Bintray上发布Eclipse p2存储库。
手动创建repo / product / version并填充文件部分可行,但对于生产环境,需要可靠的可脚本化解决方案。
目的
将Eclipse p2存储库部署到Bintray。
Eclipse p2存储库是什么?
(抱歉Eclipse的朋友们,但对于Bintry支持人员,我们最好定义一下我们正在谈论什么)。
Eclipse p2存储库是一个文件夹,必须在单个URL上发布,并且该URL必须稳定且不会更改,即使在时间上发布了多个版本。
使用Tycho Maven插件的最新版本生成的Eclipse p2存储库文件夹具有以下结构:
- 根目录下的5个文件(
p2.index
,artifacts.jar
,artifacts.xml.xz
,content.jar
,content.xml.xz
) - 2个子文件夹,
plugins
和features
,每个文件夹中都有多个.jar
文件,具有特定版本名称,例如ilg.gnuarmeclipse.core_3.3.1.201702251311.jar
例如:
artifacts.jar
artifacts.xml.xz
content.jar
content.xml.xz
features
ilg.gnuarmeclipse.codered_1.1.1.201702231729.jar
...
p2.index
plugins
ilg.gnuarmeclipse.codered_1.1.1.201702231729.jar
...
我需要部署的确切p2存储库文件夹如下:
- https://sourceforge.net/projects/gnuarmeclipse/files/Eclipse/updates/
- https://sourceforge.net/projects/gnuarmeclipse/files/Eclipse/updates-test/
在Eclipse中访问这两个p2存储库所需配置的实际URL如下: 访问这些p2存储库实际上是对这些URL直接下面的文件进行访问的序列,例如:
$ curl -L http://gnuarmeclipse.sourceforge.net/updates/p2.index
#Sat Feb 25 15:11:37 EET 2017 version=1
metadata.repository.factory.order=content.xml.xz,content.xml,\!
artifact.repository.factory.order=artifacts.xml.xz,artifacts.xml,\!
$
使用版本特定的子文件夹
Eclipse p2仓库没有版本特定的子文件夹,两个使用的子文件夹(plugins
和features
)在每个版本中都具有相同的名称;因此无法访问版本特定的子文件夹。
因此,部署多个版本不应创建版本特定的子文件夹,因为它们的内容将被忽略。
使用版本特定的URL
Eclipse插件内部配置了一个单一的URL,可用于自动获取新更新。这是p2仓库的URL,不能更改为指向版本特定的URL,因此要使更新工作正常,p2仓库应具有唯一的URL。
Eclipse p2仓库生命周期
Eclipse p2仓库的生命周期应允许新版本完全替换先前的版本,即顶部5个文件和两个子文件夹应全部属于单个版本;如果由于任何原因发布失败,则应继续显示先前的版本,而不进行更改。
- 一旦发布了版本,与其关联的文件将永远不会更改,因此不需要允许将给定文件替换为具有相同名称但内容不同的文件
- 然而,顶部文件和文件夹在所有发布版本中都具有相同的名称,服务器应允许上传它们,而不会抱怨名称已经被先前版本上传
- 发布新版本的时间点事先未知,可能每个月发布一次,但也可能间隔超过180天发布一次
发布到产品/版本URL
第一次尝试是将所有文件上传到产品/版本URL,使用以下bash函数:
curl \
--request PUT \
--upload-file "${file_absolute_path}" \
--user ${BINTRAY_USER}:${BINTRAY_API_KEY} \
"${API}/content/${BINTRAY_OWNER}/${repo}/${package}/${version}/${file_relative_path}?publish=1?override=1?explode=0"
上传成功:
Processing artifacts.jar file...
{"message":"success"}
Processing artifacts.xml.xz file...
{"message":"success"}
Processing content.jar file...
{"message":"success"}
Processing content.xml.xz file...
{"message":"success"}
Processing p2.index file...
{"message":"success"}
Processing feature: features/ilg.gnuarmeclipse.codered_1.1.1.201702231729.jar file...
{"message":"success"}
Processing plugin: plugins/ilg.gnuarmeclipse.codered_1.1.1.201702231729.jar file...
{"message":"success"}
但是,尽管所有文件都被相同地上传,但有些文件存储在repo文件夹中,而不是预期的product/version文件夹中:
artifacts.xml.xz
content.xml.xz
features
ilg.gnuarmeclipse.codered_1.1.1.201702231729.jar
pack3
3.2.1-201701141320
artifacts.jar
content.jar
p2.index
plugins
ilg.gnuarmeclipse.codered_1.1.1.201702231729.jar
请注意,虽然我没有明确地将
list_in_downloads
属性设置为任何文件,但是上传到产品/版本的某些文件被移动到了父存储库文件夹中。可以看到,
*.xz
文件和 features
和 plugins
文件夹被“提升”到存储库文件夹中,而 *.jar
文件和 p2.index
文件被忽略。使用此过程创建的存储库为:
使用不同的 POST 方法发布到产品/版本 URL
如文档所述,有 3 种传递参数给 curl 的方法。之前的测试使用了其中一种;在另外两个测试中,我尝试了下面的上传代码中的另外两种方法:curl \
--request PUT \
--upload-file "${file_absolute_path}" \
--user ${BINTRAY_USER}:${BINTRAY_API_KEY} \
--header "X-Bintray-Package: ${package}" \
--header "X-Bintray-Version: ${version}" \
--header "X-Bintray-Publish: 1" \
--header "X-Bintray-Override: 1" \
--header "X-Bintray-Explode: 0" \
"${API}/content/${BINTRAY_OWNER}/${repo}/${file_relative_path}"
并且可以与之分开使用
curl \
--request PUT \
--upload-file "${file_absolute_path}" \
--user ${BINTRAY_USER}:${BINTRAY_API_KEY} \
"${API}/content/${BINTRAY_OWNER}/${repo}/${file_relative_path};bt_package=${package};bt_version=${version};publish=1;override=1;explode=0"
两个版本都比上一次测试表现更好,第一个版本的上传成功了,并且文件夹结构得到了保留:
artifacts.jar
artifacts.xml.xz
content.jar
content.xml.xz
features
ilg.gnuarmeclipse.codered_1.1.1.201701141320.jar
p2.index
plugins
ilg.gnuarmeclipse.codered_1.1.1.201701141320.jar
但在上传第二个版本时,大部分文件都没有问题,只有上传 artifacts.xml.xz
和 content.xml.xz
两个文件失败了:
Upload 'artifacts.jar' to '/repo6/pack6/3.3.1-201702251311/'
{"message":"success"}
Upload 'artifacts.xml.xz' to '/repo6/pack6/3.3.1-201702251311/'
{"message":"Unable to upload files: An artifact with the path 'artifacts.xml.xz' already exists under another version"}
Upload 'content.jar' to '/repo6/pack6/3.3.1-201702251311/'
{"message":"success"}
Upload 'content.xml.xz' to '/repo6/pack6/3.3.1-201702251311/'
{"message":"Unable to upload files: An artifact with the path 'content.xml.xz' already exists under another version"}
Upload 'p2.index' to '/repo6/pack6/3.3.1-201702251311/'
{"message":"success"}
...
请注意,据我所知,这些文件并没有什么特别的。
使用此过程创建的存储库为:
https://dl.bintray.com/ilg-ul/repo6/
虽然它看起来像是有效的p2存储库,但实际上不是,因为大多数文件来自第二个版本,但artifacts.xml.xz和content.xml.xz来自第一个版本,因此该存储库不一致。
发布到repo URL
虽然官方文档中没有提到,但一些人建议尝试上传到较短的路径,对应于根目录或repo URL。
我使用以下代码进行了尝试:
curl \
--request PUT \
--upload-file "${file_absolute_path}" \
--user ${BINTRAY_USER}:${BINTRAY_API_KEY} \
"${API}/content/${BINTRAY_OWNER}/${repo}/${file_relative_path}?publish=1?override=1"
但是在这种情况下,大多数文件都出现了错误:
Processing artifacts.jar file...
{"message":"success"}
Processing artifacts.xml.xz file...
{"message":"Invalid file path and name"}
Processing content.jar file...
{"message":"success"}
Processing content.xml.xz file...
{"message":"Invalid file path and name"}
Processing p2.index file...
{"message":"success"}
Processing feature: features/ilg.gnuarmeclipse.codered_1.1.1.201702231729.jar file...
{"message":"Invalid file path and name"}
Processing plugin: plugins/ilg.gnuarmeclipse.codered_1.1.1.201702231729.jar file...
{"message":"Invalid file path and name"}
看起来上传机制很挑剔,只接受一些文件(如
artifacts.jar
、content.jar
和p2.index
)上传到仓库URL,但对于其他所有文件都会失败。使用此过程创建的存储库为:
同时发布到仓库和产品/版本URL
我还尝试选择性地将一些文件上传到仓库,将一些文件上传到产品/版本(artifacts.xml.xz
,content.xml.xz
以及features
/plugins
文件夹);这样创建了一个正确的p2,但当我尝试为另一个版本重复此过程时,出现了错误:Processing artifacts.jar file...
{"message":"success"}
Processing artifacts.xml.xz file...
{"message":"Unable to upload files: An artifact with the path 'artifacts.xml.xz' already exists under another version"}
Processing content.jar file...
{"message":"success"}
Processing content.xml.xz file...
{"message":"Unable to upload files: An artifact with the path 'content.xml.xz' already exists under another version"}
Processing p2.index file...
{"message":"success"}
override
标志
请注意,所有测试都设置了override
标志。
publish
标志
请注意,所有测试都设置了publish
标志,尽管这不是预期的行为。
为了保持仓库的一致性,预期行为是尝试上传所有文件不带发布标志,并在最后才执行发布操作,仅当所有文件都正确上传时才进行发布;如果发生错误而没有发布命令,则预计先前版本已发布的文件仍将可访问。
完整的测试脚本
这些测试(以及更多测试)使用的完整bash脚本可从GitHub gists获取:
要下载此脚本,请使用以下命令
mkdir -p "${HOME}/Downloads"
curl -L https://gist.github.com/ilg-ul/568a6806d5e97fcc1384d7acda4ffe36/raw/2df98f4899862f1d7e65f1601ccdbd320dce9021/bintray-test.sh -o "${HOME}/Downloads/bintray-test.sh"
此脚本需要在环境中设置以下变量:
export BINTRAY_USER=<user>
export BINTRAY_API_KEY=<auth>
export BINTRAY_OWNER=${BINTRAY_USER}
运行脚本,请输入:
bash "${HOME}/Downloads/bintray-test.sh"
问题识别
服务器拒绝上传artifacts.xml.xz
和content.xml.xz
考虑到使用不同的POST方法(repo6)发布到产品/版本URL是最先进的测试,唯一识别出的问题是服务器拒绝上传artifacts.xml.xz
和content.xml.xz
。
创建中间文件夹并存储内容
将包和版本作为URL的一部分传递(repo3)会产生最奇怪的结果,会有额外的文件夹:
pack3
3.2.1-201701141320
artifacts.jar
content.jar
p2.index
除了这三个文件之外,其他所有文件都已经正确上传,但是这三个文件的处理方式非常特殊(我认为是错误的)。
试图发布到Bintray仓库URL的大部分文件都失败了。如果这不是一种合法的发布方式,请忽略该部分,但是尝试将以下3个文件(artifacts.jar、content.jar和p2.index)发布到仓库URL是成功的,而对于其他所有文件都失败了。
基于现有文档,我没有找到可靠的方法来将普通的Eclipse p2仓库发布到Bintray上。我看到了一些提案,提供了一些奇怪的解决方案来提交复合p2仓库,但是这不是我的情况。我有两个普通的仓库,它们不需要任何版本控制,分别是http://gnuarmeclipse.sourceforge.net/updates和http://gnuarmeclipse.sourceforge.net/updates-test,并希望将它们发布到Bintray上。
如这些测试所证明的那样,Bintray的通用仓库并不是那么通用,因为它们不能像预期的那样平等地处理所有文件;看起来他们尝试支持Eclipse p2仓库,并且修改了服务器上传代码以不同的方式处理某些Eclipse文件,但结果并不完全有效,并且非常令人困惑。相反,如果Bintray支持一种新的仓库类型“Eclipse p2”,那将是非��好的,其中没有产品、版本,每次发布都允许删除所有现有文件并添加新文件。这相当于允许在仓库文件夹中发布,并允许稍后随时删除和上传文件。如果无法摆脱版本控制机制,则可以将其发布到版本文件夹中,但是请自动将最新版本的文件也显示在产品文件夹中,如repo6中所示,以确保接受所有文件,包括artifacts.xml.xz和content.xml.xz。
经过与Bintray支持团队数不清的消息交换,他们最终理解了问题并提供了一个修复程序。现在运行该脚本对于测试4、5和6是功能性的,它们基本上是相同的,只是传递信息给Bintray的方式略有不同。
测试结果如下:
- 将文件上传到存储库的根目录无法正常工作。 - 直接上传文件,将包和版本指定为文件目标路径的路径前缀无法正常工作。 - 使用HTTP头指定包和版本进行上传是可行的。 - 使用HTTP矩阵参数指定包和版本进行上传是可行的。
总之,不要尝试上传到根URL,并使用HTTP头或HTTP矩阵参数。
2017-07-31更新:
我已经在Bintray上托管更新站点几个月了,事情看起来还不错:https://bintray.com/gnu-mcu-eclipse。
用于发布的实际脚本是:https://github.com/gnu-mcu-eclipse/eclipse-plugins/blob/develop/scripts/publish-updates.sh 用于更新站点的公共URL看起来像:https://dl.bintray.com/gnu-mcu-eclipse/updates。
实际上有多个Bintray存储库,用于项目的不同“阶段”(https://bintray.com/gnu-mcu-eclipse);其中有一个单独的Bintray包(我称之为
p2
),并且在其下面有多个Bintray版本(https://bintray.com/gnu-mcu-eclipse/v4-neon-updates-experimental/p2)。
bt_package=...;bt_version=...
传递参数,并成功上传了存储库的第一个版本。不幸的是,当我发布第二个版本时,两个文件 (artifacts.xml.xz
和content.xml.xz
) 没有被上传,而是保留了第一个版本的相同文件;存储库不再一致。 :-( - ilgoverride=1
。请参见 https://bintray.com/docs/api/#_upload_content - Thomas Fritsch