Gradle发布尝试将RPM两次上传到Artifactory YUM存储库的尝试,第二次失败并显示403 [英] Gradle publish attemps to upload RPM to Artifactory YUM repo twice, second time fails with 403

查看:296
本文介绍了Gradle发布尝试将RPM两次上传到Artifactory YUM存储库的尝试,第二次失败并显示403的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用gradle和ivy-publish插件将RPM工件发布到Artifactory上的本地YUM存储库.我遇到的问题是,发布任务似乎试图上载工件两次,而第二次尝试失败(正确),HTTP状态码为403.我通过身份验证的工件用户具有部署/缓存特权,但没有删除权限.

我的问题是,为什么发布任务尝试两次上传工件?

我包括我的gradle配置和以下人工日志文件的摘录.请注意,RPM是使用netflix os-package构建的

Gradle Config发布配置:

apply plugin: "ivy-publish"

publishing {
    publications {
        rpm(IvyPublication) {
            artifact  buildRpm.outputs.getFiles().getSingleFile()
            /* Ivy plugin forces an organisation to be set. Set it to anything
               as the pattern layout later supresses it from appearing in the filename */
            organisation 'dummy'
        }
    }
    repositories {
        ivy {
            credentials {
                username 'username'
                password 'password'
            }
            url 'http://my.artifactory.com/artifactory/yum-dev-local/'
            layout "pattern", {
                artifact "${buildRpm.outputs.getFiles().getSingleFile().getName()}"
            }
        }
    }
}

要构建和发布工件,我需要执行以下操作(在工件上有一个空白的yum-local存储库)

./gradlew clean buildRpm publish

产生以下内容:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':my-artifact-service:publishRpmPublicationToIvyRepository'.
> Failed to publish publication 'rpm' to repository 'ivy'
> java.io.IOException: Could not PUT   'http://my.artifactory.com/artifactory/yum-dev-local/my-artifact-service-0.0.1-1.el7.x86_64.rpm'. Received status code 403 from server: Forbidden

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Artifactory日志显示:

2016-10-12 15:41:41,828 [http-nio-8081-exec-92] [INFO ] (o.a.e.UploadServiceImpl:453) - Deploy to 'yum-dev-local:my-artifact-service-0.0.1-1.el7.x86_64.rpm' Content-Length: 4420
2016-10-12 15:41:41,842 [http-nio-8081-exec-64] [INFO ] (o.a.e.UploadServiceImpl:299) - Deploy to 'yum-dev-local:my-artifact-service-0.0.1-1.el7.x86_64.rpm.sha1' Content-Length: 40
2016-10-12 15:41:41,850 [http-nio-8081-exec-90] [WARN ] (o.a.r.ArtifactoryResponseBase:105) - Sending HTTP error code 403: Not enough permissions to overwrite artifact 'yum-dev-local:my-artifact-service-0.0.1-1.el7.x86_64.rpm' (user 'username' needs DELETE permission).

最后一条日志行指示已请求再次放入工件.当我检查仓库时,工件确实已经成功上传,但是发布任务失败了.有人可以指出这是怎么回事吗?

版本:

------------------------------------------------------------
Gradle 2.14.1
------------------------------------------------------------

Build time:   2016-07-18 06:38:37 UTC
Revision:     d9e2113d9fb05a5caabba61798bdb8dfdca83719

Groovy:       2.4.4
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_73 (Oracle Corporation 25.73-b02)
OS:           Linux 4.3.5-300.fc23.x86_64 amd64

解决方案

之所以发生这种情况,是因为Gradle Ivy发布插件将推送除您的工件之外的 3个额外文件,这些文件是:

  • 一个.sha1文件,其中包含工件的校验和
  • .xml Ivy软件包文件,其中包含有关工件的信息
  • 上一个xml的.sha1文件

问题在于第一个.sha1文件.上传此文件时,Artifactory/JFrog会认为您想覆盖以前上传的具有相同名称的工件,因此会出现错误.

您会认为仅授予DELETE权限即可解决此问题,但事实并非如此.这样做只会用校验和.sha1文件替换您以前上传的软件包,并且由于该文件不是有效的.deb文件(在我的情况下是您的.rpm文件),因此在解压缩并生成Debian存储库结构时,它将只会清除您的原始工件,因此您将无法正确下载.

不幸的是,没有解决此问题的方法,因为没有办法告诉Ivy/Gradle不生成这些我知道的其他文件(//github. com/gradle/gradle/blob/master/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolver.java#L266 )

最后,我采用的解决方案是直接使用curl直接将其放置到Artifactory/JFrog,这实际上减少了代码,但增加了OS依赖性(curl).如果您对此感到担心,则可以使用Gradle HTTP库执行相同的操作:

task uploadArtifactory(type: Exec) {

    def artifact = buildDeb.outputs.getFiles().filter {
        it.getAbsolutePath().endsWith ".deb"
    }.getSingleFile()

    commandLine "curl",
        "-X",
        "PUT",
        "https://$artifactoryUser:$artifactoryPassword@$artifactoryAccount.jfrog.io/$artifactoryAccount/$artifactoryRepo/pool/${project.name}_${version}_all.deb;deb.distribution={...};deb.component=main;deb.architecture=all",
        "--upload-file",
        artifact
}

I'm trying to publish an RPM artifact to a local YUM repo on Artifactory using gradle and the ivy-publish plugin. The issue I'm having is that the publish tasks appears to attempt to upload the artifact twice, and the second attempt fails (correctly) with a HTTP status code of 403. The artifactory user I authenticate with has deploy/cache privileges but not delete.

My question is why is the publish task attempting to upload the artifact twice?

I include my gradle configuration and an extract from the artifactory log file below. Note that the RPM is build using the netflix os-package

Gradle Config Publishing Configuration:

apply plugin: "ivy-publish"

publishing {
    publications {
        rpm(IvyPublication) {
            artifact  buildRpm.outputs.getFiles().getSingleFile()
            /* Ivy plugin forces an organisation to be set. Set it to anything
               as the pattern layout later supresses it from appearing in the filename */
            organisation 'dummy'
        }
    }
    repositories {
        ivy {
            credentials {
                username 'username'
                password 'password'
            }
            url 'http://my.artifactory.com/artifactory/yum-dev-local/'
            layout "pattern", {
                artifact "${buildRpm.outputs.getFiles().getSingleFile().getName()}"
            }
        }
    }
}

To build and publish the artifact I execute the following (with an empty yum-local repo on artifactory)

./gradlew clean buildRpm publish

which produces the following:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':my-artifact-service:publishRpmPublicationToIvyRepository'.
> Failed to publish publication 'rpm' to repository 'ivy'
> java.io.IOException: Could not PUT   'http://my.artifactory.com/artifactory/yum-dev-local/my-artifact-service-0.0.1-1.el7.x86_64.rpm'. Received status code 403 from server: Forbidden

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

The Artifactory log shows:

2016-10-12 15:41:41,828 [http-nio-8081-exec-92] [INFO ] (o.a.e.UploadServiceImpl:453) - Deploy to 'yum-dev-local:my-artifact-service-0.0.1-1.el7.x86_64.rpm' Content-Length: 4420
2016-10-12 15:41:41,842 [http-nio-8081-exec-64] [INFO ] (o.a.e.UploadServiceImpl:299) - Deploy to 'yum-dev-local:my-artifact-service-0.0.1-1.el7.x86_64.rpm.sha1' Content-Length: 40
2016-10-12 15:41:41,850 [http-nio-8081-exec-90] [WARN ] (o.a.r.ArtifactoryResponseBase:105) - Sending HTTP error code 403: Not enough permissions to overwrite artifact 'yum-dev-local:my-artifact-service-0.0.1-1.el7.x86_64.rpm' (user 'username' needs DELETE permission).

The last log line indicates that a request was made to PUT the artifact again. When I check the repo, the artifact has indeed been successfully uploaded, however the publish task is failing. Can someone point out what is going on here?

Versions:

------------------------------------------------------------
Gradle 2.14.1
------------------------------------------------------------

Build time:   2016-07-18 06:38:37 UTC
Revision:     d9e2113d9fb05a5caabba61798bdb8dfdca83719

Groovy:       2.4.4
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_73 (Oracle Corporation 25.73-b02)
OS:           Linux 4.3.5-300.fc23.x86_64 amd64

解决方案

This is happening because the Gradle Ivy publishing plugin will push, apart from your artifact, 3 extra files, which are:

  • A .sha1 file which contains a checksum of your artifact
  • A .xml Ivy package file, which contains information about the artifact
  • a .sha1 file for the previous xml

The problem is with the first .sha1 file. When uploading this, Artifactory / JFrog will think that you want to overwrite the previously uploaded artifact, which has the same name, hence the error.

You would think that just giving DELETE permissions would fix the issue, but that is not the case. Doing that will just replace your previously uploaded package with a checksum .sha1 file, and since that kind of file is not a valid .deb file (in my case, .rpm in yours), when unpacking and generating the Debian repository structure, it will just wipe out your original artifact, so you would not be able to download properly.

Unfortunately, there is not fix for this problem since there is no way of telling Ivy / Gradle to not generate these additional files, that I know of (https://github.com/gradle/gradle/blob/master/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolver.java#L266)

Finally, the solution I went with is to just PUT to Artifactory / JFrog directly using curl, which results in actually less code, but an additional OS dependency (curl). If you are worried about that, you can just use an Gradle HTTP library to do the same thing:

task uploadArtifactory(type: Exec) {

    def artifact = buildDeb.outputs.getFiles().filter {
        it.getAbsolutePath().endsWith ".deb"
    }.getSingleFile()

    commandLine "curl",
        "-X",
        "PUT",
        "https://$artifactoryUser:$artifactoryPassword@$artifactoryAccount.jfrog.io/$artifactoryAccount/$artifactoryRepo/pool/${project.name}_${version}_all.deb;deb.distribution={...};deb.component=main;deb.architecture=all",
        "--upload-file",
        artifact
}

这篇关于Gradle发布尝试将RPM两次上传到Artifactory YUM存储库的尝试,第二次失败并显示403的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆