On 11/04/2012, at 6:48 PM, Luke Daley wrote:
>
> On 11/04/2012, at 12:23 AM, Adam Murdoch wrote:
>
>> On 10/04/2012, at 7:49 PM, Luke Daley wrote:
>>
>>> http://forums.gradle.org/gradle/topics/signing_plugin_add_to_configuration_even_if_its_not_being_run
>>>
>>> The signing plugin adds PublishArtifacts for each signature file. These
>>> signature files may not actually be created depending on the signing
>>> configuration:
>>>
>>> signing {
>>> required { project.taskGraph.hasTask("uploadArchives") }
>>> sign configurations.archives
>>> }
>>>
>>> This “required” handling makes it easy to have a build that works for
>>> people who don't have their environment set up for signing. If signing is
>>> not required, and we can't sign, the signing task(s) is skipped so we end
>>> up with the PublishArtifacts on the configuration pointing to non existent
>>> files.
>>>
>>> The problem comes in that the Artifactory plugin tries to upload these non
>>> existent files and explodes.
>>>
>>> One idea is to allow this as part of the model. That is, a PublishArtifact
>>> becomes something that might be created during the build instead of
>>> something that will be created.
>>
>> I think the problem here is that the signatures aren't really artefacts, in
>> the sense that the point of the build is not to generate signatures, the
>> point of the build is to build the jar or war or whatever it is that is
>> being signed. Signatures are more like meta-data about artefacts, that are
>> used as part of shipping the real artefacts around between machines and
>> teams and so on.
>>
>> I would instead think about splitting publications up into 2 pieces:
>> * The definition of the component that is being produced. This defines the
>> artefacts that are fundamental to the component that always need to be
>> build: the jar or the dll or the distribution zip or whatever.
>> * The definition of the destination-specific publication. This defines the
>> artefacts that will be published to the given destination, where destination
>> is a repository. This would (by default) include the artefacts of the
>> components being published. It might also include signatures or checksums or
>> meta-data artefacts or whatever additional artefacts need to be published to
>> this destination.
>>
>> This way, there's no need for conditional signing or PublishArtifacts. If
>> you are building locally, the signing is not triggered. If you've declared
>> that signatures are required to publish to the corporate repository, then
>> you need to have signing set up if you want to publish there and its a
>> failure if you don't.
>
> I'm not sure about expressing the requiredness of something purely as a
> function of where it's going. That's too rigid in my opinion. One example is
> that you may want to say that signatures are only required if we are doing a
> final release, and you may not be using separate destinations for final and
> non-final releases. I think it's much safer to allow the user to control this
> for whatever case they need. We can apply patterns over the top of course.
>
> Also, rather than destination-specific publications I think we should be
> aiming for aggregate & filtered publications which can then be used in
> whichever way the user wants. Tying it to a destination seems like inflexible
> coupling to me.
We're talking about the same thing here, I think. I've described the pattern,
with the implicit assumption that it sits on top of an un-opionated toolkit.
You've described the toolkit, with (I'm guessing) the assumption that an
opinionated convention sits on top of it.
>
> I agree that we need to be able to model metadata, but I think that's an
> entirely separate issue. It's feasible to me that the build might not produce
> first class artifacts under certain conditions and that being ok. You can do
> this right now of course by never modelling the optional thing if we aren't
> going to make it, but that implies that you can make the decision reasonably
> early which may not be the case.
I'm pretty sure that the optional things are a function of what you're
building, and not a function of who you are or where you are. I also think
there's generally only a small number of ways a given project needs to be
published. So, for example, you might have a local build, a CI build or a
release build, or in other words, 3 different combinations of artefacts.
The solution, to me, is to use composition to model this. First, you model the
things that the project inherently produces: a java library, a native
application, whatever. These are the 'components' that the project produces.
For each such component, you would define the artifacts that represent the
component, that you need in order to use the component: the jar, the executable
or install image or whatever. This would not include auxiliary artifacts like
signatures or checksums. Implementation-wise, a component would be modelled as
something like a buildable set of publish artefacts + some dependency
meta-data. So, we have something like this:
PublishArtifactsSet is-a Buildable
PublishArtifactSet has-a set of PublishArtifacts
ConfigurablePublishArtifactSet is-a PublishArtifactSet that allows composition,
etc, similar to ConfigurableFileCollection.
Component has-a ConfigurablePublishArtifactSet
Project has-a set of named Components
Then, you model the different ways you want to publish these components: you
might have, say, a local and a release publication. Each publication is
essentially just a set of artefacts. Implementation-wise, a publication is
modelled as a PublishArtifactSet, and is usually a transformation of some other
PublishArtifactSet (typically a Component, but could be anything that can be
converted into a set of artefacts), to add in signatures and checksums and
whatever else. So we have something like this:
Publication has-a ConfigurablePublishArtifactSet
SigningArtifactSet is-a PublishArtifactSet
SigningArtifactSet transforms a PublishArtifactSet, and contains a signature
artifact for each artefact in the original set.
ChecksumArtifactSet, PomArtifactSet, IvyXmlArtifactSet do similar things.
Project has-a set of named Publications
Finally, you wire together some tasks to publish these publications to various
destinations. Implementation-wise, a publish task would take an
ArtifactRepository and a PublishArtifactSet, and would push the given artefacts
to the given destination. Probably there would be a bunch of task rules, as we
have now, perhaps something like:
assemble${componentName} - builds the artefacts of the component
(alternatively, the rule might just be ${componentName})
assemble${publicationName} - builds the artefacts of the publication
publish${publicationName} - builds and publishes the artefacts of the
publication to all repositories
assemble - builds all components
publish - builds and publishes all publications.
So, we have all the pieces. Out of the box, there'd be no components or
publications defined.
Applying a convention plugin (java, cpp-exe, application, war, etc) would add
components of the appropriate type. The java plugin would add a java library,
war plugin would add a web application, and so on.
Applying the maven plugin would add a maven-style publication for each
component, and probably define publish tasks that attach each maven publication
to each maven repository.
Applying the ivy plugin would add an ivy-style publication for each component,
and the appropriate publish tasks.
Applying the signing base plugin (whether that's the current signing plugin or
a new one) would add the capability to sign Publications (or probably
PublishArtifactSet more generally), but not actually add any signatures.
Applying the signing convention plugin , would add signatures to each remote
publication.
This way, you can go with the conventions, or compose your own model. There's
no need for conditional signing or artefacts, as everything you need is just a
dependency of what you're building. Your 'releaseBuild' task can depend on
'publishRelease', your 'ciBuild' task can depend on 'publishSnapshot', and your
'devBuild' task can depend on 'assemble'.
--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com