CI | java python tutorial Wed 06 June 2012 Olivier Mansion

In our first blog post dedicated to Python and Java, we saw how Maven can orchestrate a unified build process for these two languages.

In the last one, we saw how to synchronize versions between Java projects and Python projects.

Now it's time to automate our release and deployment workflow:

  • create a tag for each release (on GitHub, see here to setup your Git environment),
  • deploy Java artifacts on a distant repository. We are using a Nexus instance configured with two hosted repositories (snapshots and releases, their names being quite straightforward) and a public group repository grouping the hosted ones plus a proxy on Maven Central
  • deploy Python artifacts on a private PyPI (could be a fork of or Django running a djangopypi application)

To do so, we'll use the maven-release-plugin. If you want to follow this article with the sources of the sample project, feel free to clone it from GitHub.

Most of the Maven configuration takes place in the root pom.xml. First add the source management details:

1 <project>
2   <scm>
3     <connection>scm:git:git://</connection>
4     <developerconnection></developerconnection>
5     <url></url>
6   </scm>
7 </project>

Then declare the repositories for snapshot and release artifacts (matching the Nexus ones):

 1 <project>
 2   <distributionmanagement>
 3     <repository>
 4       <id>releases</id>
 5       <name>Releases</name>
 6       <url></url>
 7     </repository>
 8     <snapshotrepository>
 9       <id>snapshots</id>
10       <name>Snapshots</name>
11       <url></url>
12     </snapshotrepository>
13   </distributionmanagement>
14 </project>

Also add the maven-release-plugin configuration, note the autoVersionSubmodules tag that tells maven that all projects have the same version:

 1 <project>
 2   <build>
 3     <pluginmanagement>
 4       <plugins>
 5         <plugin>
 6           <groupid>org.apache.maven.plugins</groupid>
 7           <artifactid>maven-release-plugin</artifactid>
 8           <version>2.2.2</version>
 9           <configuration>
10             <goals>clean deploy</goals>
11             <autoversionsubmodules>true</autoversionsubmodules>
12             <tagnameformat>tutorial-python-java-@{project.version}</tagnameformat>
13           </configuration>
14         </plugin>
15       </plugins>
16     </pluginmanagement>
17   </build>
18 </project>

Copy this settings.xml in $HOME/.m2 folder and edit it to modify the Nexus url and the credentials for the nexus, <i>releases</i> and snapshots repositories.

Now it's time to handle the Python side. We saw that the deploy goal is mapped with the python register sdist upload command. We first need to declare the private PyPI in the $HOME/.pypirc file (replace the credentials and the private PyPI url):

 1 [distutils]
 2 index-servers =
 3     pypi
 4     private
 6 [pypi]
 7 username = xxx
 8 password = xxx
10 [private]
11 repository =
12 username = xxx
13 password = xxx

Then we need to tell that the pysample project must be deployed on the private PyPI. To do so, modify or create a setup.cfg file along the and append the following lines:

1 [register]
2 repository = private
4 [upload]
5 repository = private

We're now ready to release and deploy. To release, issue the following command and answer the questions:

1 $ mvn release:prepare
2 [...]
3 What is the release version? 0.3
4 What is SCM release tag or label? tutorial-python-java-0.3
5 What is the new development version? 0.4-SNAPSHOT
6 [...]

Your project is now released, time to go threw our final step, the deployment:

 1 $ mvn release:perform
 2 [...]
 3 [INFO] Registering pysample to
 4 [INFO] Server response (200): OK
 5 [...]
 6 [INFO] Submitting dist/pysample-0.3.tar.gz to
 7 [INFO] Server response (200): OK
 8 [...]
 9 [INFO] Uploading:
10 [...]

In addition to a Hosted Continuous Integration Service, ShiningPanda also offers build and release management expertise, so if you have questions or if you are stuck with your internal build process do not hesitate to contact our service team!