Single Site Eclipse Workspace

This guide explains how to build and deploy a “workspace” - a set of related projects - using Tycho/Maven and featuring a single site with a P2 repository and product binaries for Eclipse products.

A workspace includes:

  • Bundle projects.
  • Feature project(s).
  • Parent project. You can also have an aggregator project, but it is not covered here.
  • Repository project.

This guide assumes that you already know how to build plug-ins, OSGi bundles, and Eclipse applications with Tycho and focuses on the part of building a Maven site and deploying the site along with the sources, p2 repository, and an Eclipse product if you have one.

Parent project

Add the following plug-in to the pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-site-plugin</artifactId>
    <version>3.7.1</version>
    <configuration>
        <skip>true</skip>
        <skipDeploy>true</skipDeploy>
    </configuration>
</plugin>		

It tells Maven to skip site building and deploying for all plug-ins unless overridden.

Repository project

Create a site under src\site - see Maven site for more details.

Add siteDir property:

<properties>
	<siteDir>${project.artifactId}/${project.version}</siteDir>
</properties>

Add

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-site-plugin</artifactId>
    <configuration>
        <skip>false</skip>
        <skipDeploy>false</skipDeploy>
    </configuration>
</plugin>		

under build/plugins. It overrides parent settings.

Add

<extensions>
	<!-- Enabling the use of FTP -->
	<extension>
		<groupId>org.apache.maven.wagon</groupId>
		<artifactId>wagon-ftp</artifactId>
		<version>3.0.0</version>
	</extension>
</extensions>

under build. The above snippet uses FTP for deployment. You can use some other protocol.

Copy repository and other resources to the site using maven-resources-plugin. The below snippet shows copying the repository and models and API documentation from other bundles.

<plugin>
	<artifactId>maven-resources-plugin</artifactId>
	<version>3.0.1</version>
	<executions>
		<execution>
			<id>copy-repository</id>
			<phase>pre-site</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<outputDirectory>${basedir}/target/site</outputDirectory>
				<resources>
					<resource>
						<directory>${basedir}/target</directory>
						<includes>
							<include>repository/**</include>
							<include>org.nasdanika.codegen.repository-*.zip</include>
						</includes>
						<filtering>false</filtering>
					</resource>
				</resources>
			</configuration>
		</execution>
		<execution>
			<id>copy-modeldoc</id>
			<phase>pre-site</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<outputDirectory>${basedir}/target/site/modeldoc</outputDirectory>
				<resources>
					<resource>
						<directory>${basedir}/../org.nasdanika.codegen.editor/doc/site</directory>
						<filtering>false</filtering>
					</resource>								
				</resources>
			</configuration>
		</execution>
		<execution>
			<id>copy-model-javadoc</id>
			<phase>pre-site</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<outputDirectory>${basedir}/target/site/apidocs/model</outputDirectory>
				<resources>
					<resource>
						<directory>${basedir}/../org.nasdanika.codegen/target/site/apidocs</directory>
						<filtering>false</filtering>
					</resource>								
				</resources>
			</configuration>
		</execution>
		<execution>
			<id>copy-edit-javadoc</id>
			<phase>pre-site</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<outputDirectory>${basedir}/target/site/apidocs/edit</outputDirectory>
				<resources>
					<resource>
						<directory>${basedir}/../org.nasdanika.codegen.edit/target/site/apidocs</directory>
						<filtering>false</filtering>
					</resource>								
				</resources>
			</configuration>
		</execution>
		<execution>
			<id>copy-editor-javadoc</id>
			<phase>pre-site</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<outputDirectory>${basedir}/target/site/apidocs/editor</outputDirectory>
				<resources>
					<resource>
						<directory>${basedir}/../org.nasdanika.codegen.editor/target/site/apidocs</directory>
						<filtering>false</filtering>
					</resource>								
				</resources>
			</configuration>
		</execution>					
	</executions>
</plugin>

Add distribution management and URL as shown in the example below:

<url>https://www.nasdanika.org/products/${siteDir}/</url>
<distributionManagement>
	<site>
		<id>nasdanika-org</id>
		<url>ftp://${env.FTP_SERVER}/${siteDir}</url>
	</site>
</distributionManagement>	

The above snippet has a hardcored deployment directory. You may choose to add version to it and use the group id for consistency, if you have many workspaces/products.

Product deployment

If you have a product simply add product archives to the includes element in the first execution above.

Deploying sources

If you want to deploy sources of the workspace to the site follow the steps below.

Parent project

Add

<plugin>
	<artifactId>maven-assembly-plugin</artifactId>
	<version>3.1.0</version>
	<configuration>
	    <skipAssembly>true</skipAssembly>
	</configuration>
</plugin>			

It tells Maven to skip assembly unless overridden.

Repository project

Add an assembly plugin definition following the example below.

<plugin>
	<artifactId>maven-assembly-plugin</artifactId>
	<version>3.1.0</version>
	<configuration>
		<skipAssembly>false</skipAssembly>
		<outputDirectory>${project.build.directory}/site</outputDirectory>
		<formats>zip</formats>
		<finalName>server</finalName>
		<appendAssemblyId>false</appendAssemblyId>
		<descriptors>
			<descriptor>src/assembly/workspace.xml</descriptor>
		</descriptors>
	</configuration>
        <executions>
          <execution>
            <id>create-archive</id>
            <phase>pre-site</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
</plugin>			

Create src\assembly\workspace.xml similar to the one shown below:

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
  <id>project</id>
  <formats>
    <format>tar.gz</format>
    <format>tar.bz2</format>
    <format>zip</format>
  </formats>
  <fileSets>
    <fileSet>
      <directory>${project.basedir}/..</directory>
      <outputDirectory>/</outputDirectory>
      <useDefaultExcludes>false</useDefaultExcludes>
      <excludes>
        <exclude>*/target/**</exclude>
        <exclude>*.jar</exclude>
        <exclude>.git/**</exclude>
        <exclude>.circleci/**</exclude>
        <exclude>ftp-clean.xml</exclude>
      </excludes>
    </fileSet>
  </fileSets>
</assembly>

Deployment

To build and deploy use the following command: mvn clean javadoc:javadoc package site-deploy. Make sure that you have your server user name and password defined in settings.xml.

CircleCI

To build and deploy from CircleCI follow the steps below.

Create .circleci directory with two files - config.yml and settings.xml.

config.yml example:

# Java Maven CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-java/ for more details 
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
      - image: circleci/openjdk:8-jdk
      
      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      # - image: circleci/postgres:9.4

    working_directory: ~/repo

    environment:
      # Customize the JVM maximum heap limit
      MAVEN_OPTS: -Xmx3200m
    
    steps:
      - checkout
      - run: mvn -s .circleci/settings.xml clean site-deploy

settings.xml example:

<?xml version="1.0" encoding="UTF-8"?>

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <servers>
    <server>
      <id>nasdanika-org</id>
      <username>${env.FTP_USER}</username>
      <password>${env.FTP_PASSWORD}</password>
    </server>
  </servers>
</settings>

Then define FTP_SERVER, FTP_USER, and FTP_PASSWORD environment variables in CircleCI and run a build.

Cleaning the remote directory

Maven Wagon does not clean the remote folder before deployment - it just deploys over. To clean the remove folder you can use maven-antrun-plugin as shown below:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-antrun-plugin</artifactId>
	<version>1.8</version>
	<executions>
		<execution>
			<id>ftp</id>
			<phase>post-site</phase>
			<configuration>
				<target>
					<ftp passive="yes" action="mkdir" server="${env.FTP_SERVER}" userid="${env.FTP_USER}" password="${env.FTP_PASSWORD}" remotedir="/${siteDir}"/>
				
					<ftp passive="yes" action="delete" server="${env.FTP_SERVER}" userid="${env.FTP_USER}" password="${env.FTP_PASSWORD}" remotedir="/${siteDir}">
						<fileset defaultexcludes="false">
							<include name="**" />
						</fileset>
					</ftp>
					
					<ftp passive="yes" action="rmdir" server="${env.FTP_SERVER}" userid="${env.FTP_USER}" password="${env.FTP_PASSWORD}" remotedir="/${siteDir}">
						<fileset defaultexcludes="false">
							<include name="**" />
						</fileset>
					</ftp>
				</target>
			</configuration>
			<goals>
				<goal>run</goal>
			</goals>
		</execution>
	</executions>
	<dependencies>
		<dependency>
			<groupId>commons-net</groupId>
			<artifactId>commons-net</artifactId>
			<version>1.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.ant</groupId>
			<artifactId>ant-commons-net</artifactId>
			<version>1.8.1</version>
		</dependency>
	</dependencies>
</plugin>