####################
Publishing Artifacts
####################

A library owner/maintainer can *publish* versioned artifacts that
folks elsewhere can fetch and import. In the JVM world, these are jars
(with poms)
on a server that Maven (or Ivy) looks for. (In the Python world, these are
eggs; but as of late 2013, Pants doesn't help publish these.)

This page talks about publishing artifacts. We assume you already know enough
about Pants to *build* the library that underlies an artifact.
To *use* an artifact that has already been published from some other
source tree, see :doc:`3rdparty`. (To use a artifact that has been
published from *your own* source tree... don't do that. Instead, depend on
the ``*_library`` build target.)

It's tricky to keep track of versions, label artifacts with versions, and
upload those artifacts. Pants eases these tasks.

A library's build target specifies where to publish it.
For example, a :ref:`bdict_java_library` build target can have a ``provides``
parameter of type :ref:`bdict_artifact`. The ``artifact`` specifies an
"address" similar to what you might see in ``3rdparty`` ``BUILD`` files:
an artifact's location. It does *not* specify a version; that changes
each time you publish.

Pants' ``publish`` goal builds the library, bumps the library's version
number, and uploads the library to its repository. Actually, it does
quite a bit more than that.

It uses `Semantic Versioning ("semver") <http://semver.org/>`_ for versioning.
Versions are dotted number triads (e.g., 2.5.6); when Pants bumps a version,
it specifically bumps the patch number part. Thus, if the current version is
2.5.6, Pants bumps to 2.5.7. To publish a minor or major version instead of
a patch, you override the version number on the command line.

**The pushdb:** To "remember" version numbers, Pants uses the pushdb.
The pushdb is a text file under source control. It lists artifacts with
their current version numbers and SHAs. When you publish artifacts,
pants edits this file and pushes it to the origin.

*****************
Life of a Publish
*****************

To publish a library's artifact, Pants bumps the version number and uploads
the artifact to a repository. When things go smoothly, that's all
you need to know. When things go wrong, it's good to know details.

* Pants decides the version number to use based on pushdb's state.

  You can override the version number[s] to use via a command-line flag.
  Pants does some sanity-checking: If you specify an override version less
  than or equal to the last-published version (as noted in the pushdb),
  Pants balks.

* For each artifact to be published, it prompts you for confirmation.
  (This is a chance for you to notice that you want to, e.g.,
  bump an artifact's minor revision instead of patch revision.)

* Invokes a tool to upload the artifact to a repository.
  (For JVM artifacts, this tool is Ivy.)

* Commits pushdb.

Things can go wrong; you can recover:

* Uploading the artifact can fail for reasons you might expect for an upload:
  authentication problems, transient connection problems, etc.

* Uploading the artifact can fail for another reason: that artifact+version
  already exists on the server. *In theory*, this shouldn't happen: Pants
  bumps the version it found in the pushdb. But in practice, this can happen.
  It's usually a sign that something strange happened in a *previous* publish.
  Perhaps someone published an artifact "by hand" instead of using Pants.
  Perhaps someone used Pants to publish an artifact but it failed to update
  the pushdb in source control. E.g., merge conflicts can happen, and folks
  don't always recover from them correctly.

  In this situation, you probably want to pass ``--publish-override`` to
  specify a version to use instead of the automatically-computed
  already-existing version. Choose a version that's not already on the server.
  Pants records this version in the pushdb, so hopefully the next
  publisher won't have the same problem.

* Committing the pushdb can fail, even though uploading succeeded. Perhaps you
  were publishing at about the same time someone else was; you might get a
  merge conflict when trying to commit.

  (There's a temptation to ignore this error: the artifact uploaded OK; nobody
  expects a merge conflict when publishing. Alas, ignoring the error now means
  that your *next* publish will probably fail, since Pants has lost track of
  the current version number.)

  In this situation, you want to

  * Update your source tree, discarding local changes to the pushdb.
    In git, this might be a ``reset origin/master``
    (if ``master`` is your release branch) and a ``pull``.
  * Look at the pushdb's source control history to see who made the conflicting
    publish; contact them. (You're about to try again; if they also encountered
    problems, they are probably also about to try again. You might want to
    coordinate and take turns.)
  * Try publishing again.

******
How To
******

coming soon

.. TODO plagiarize "Pushing to Maven" from "Pants Tips"
   But be a little clearer. It's pretty easy to overlook "clean master branch"

*******************************
Restricting to "Release Branch"
*******************************

Your organization might have a notion of a special "release branch": you want
all publishing to happen on this source control branch, which you maintain
extra-carefully. You can
:ref:`configure your repo <setup_publish_restrict_branch>`
so the ``publish`` goal only allows ``publish``-ing from this special branch.
