Skip to content

Commit

Permalink
feat: do not create /bin/java symlink (#752)
Browse files Browse the repository at this point in the history
* feat: override _get_java_link_commands

Maven and Ant plugin should not create /bin/java symlink

* doc: add rockcraft-specific docs for ant and maven

Ant and Maven plugins override build commands of craft-parts Ant and Maven plugins.

* feat: register plugin overrides

* test: add rockcraft plugin tests

- add smoke tests for maven and ant plugins.

* lint: reformat documentation

* test: add ant dependency

* test: fix ant plugin test

- drop unneeded property
- add ant plugin targets

* test: use symlink to java when running test

* test: replace modules files

- use package installation to ensure /usr/bin/java is present
- run jlink to replace modules

* test: drop modules part

- we have not merged JAVA_HOME fix yet, so do basic tests that plugin works

* test: rollback test changes

- we still have to create java symlink in rockcraft yaml
-  the test image is fixed for amd64, so its ok to hardcode path in task.yaml

* test: do not prune docker

* fix: add /usr/bin/java symlink

* doc: update documentation with /usr/bin/java symlink

* test: use /usr/bin/java in the test

* fix: fix typo in ln command

* lint: update formatting

* lint: apply ruff fixes

* doc: reuse common docs

Reuse common docs for maven and ant plugins.

* chore: rename part in ant test

ant test had part named 'maven-sample'.

* test: validate /bin/java

Validate that /bin/java is a valid command

* lint: reformat long lines

craft-parts ant plugin description has too long lines.
  • Loading branch information
vpa1977 authored Dec 4, 2024
1 parent 7b1936d commit b7ea743
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 3 deletions.
4 changes: 2 additions & 2 deletions docs/reference/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ Rockcraft.
:maxdepth: 1

/common/craft-parts/reference/plugins/dotnet_plugin
/common/craft-parts/reference/plugins/ant_plugin
plugins/ant_plugin
/common/craft-parts/reference/plugins/autotools_plugin
/common/craft-parts/reference/plugins/cmake_plugin
/common/craft-parts/reference/plugins/dump_plugin
/common/craft-parts/reference/plugins/go_plugin
/common/craft-parts/reference/plugins/make_plugin
/common/craft-parts/reference/plugins/maven_plugin
plugins/maven_plugin
/common/craft-parts/reference/plugins/meson_plugin
/common/craft-parts/reference/plugins/nil_plugin
/common/craft-parts/reference/plugins/npm_plugin
Expand Down
64 changes: 64 additions & 0 deletions docs/reference/plugins/ant_plugin.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.. _rockcraft_ant_plugin:

Ant plugin
==========

The Ant plugin builds Java projects using the
`Apache Ant <https://ant.apache.org/>`_ build tool.

After a successful build, this plugin will:

* Create ``jar/`` directory in ``$CRAFT_PART_INSTALL``.
* Hard link the ``.jar`` files generated in ``$CRAFT_PART_BUILD`` to
``$CRAFT_PART_INSTALL/jar``.
* Find the ``java`` executable provided by the part and link it as
``$CRAFT_PART_INSTALL/usr/bin/java`` if ``/usr/bin`` exists.


Keywords
--------

In addition to the common :ref:`plugin <part-properties-plugin>` and
:ref:`sources <part-properties-sources>` keywords, this plugin provides
the following plugin-specific keywords:

ant-build-targets
~~~~~~~~~~~~~~~~~
**Type:** list of strings

The ant targets to build. These are directly passed to the ``ant`` command line.

ant-build-file
~~~~~~~~~~~~~~
**Type:** str

The name of the main XML build file. Defaults to ``build.xml``.

ant-properties
~~~~~~~~~~~~~~
**Type:** dict of strings to strings

A series of key: value pairs that are passed to ``ant`` as properties using the
``-D{key}={value}`` notation.


Environment variables
---------------------

This plugin reads the ``http_proxy`` and ``https_proxy`` variables from
the environment to configure proxy access.

Please refer to
`Running Apache Ant <https://ant.apache.org/manual/running.html>`_ for
a list of environment variables used by Ant.

.. _rockcraft_ant-details-begin:

.. include:: /common/craft-parts/reference/plugins/ant_plugin.rst
:start-after: .. _ant-details-begin:
:end-before: .. _ant-details-end:

.. _rockcraft_ant-details-end:

.. include:: /common/craft-parts/reference/plugins/ant_plugin.rst
:start-after: .. _ant-details-end:
56 changes: 56 additions & 0 deletions docs/reference/plugins/maven_plugin.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.. _rockcraft_maven_plugin:

Maven plugin
============

The Maven plugin builds Java projects using the Maven build tool.

After a successful build, this plugin will:

* Create ``jar/`` directory in ``$CRAFT_PART_INSTALL``.
* Hard link the ``.jar`` files generated in ``$CRAFT_PART_BUILD`` to
``$CRAFT_PART_INSTALL/jar``.
* Find the ``java`` executable provided by the part and link it as
``$CRAFT_PART_INSTALL/usr/bin/java`` if ``/usr/bin`` exists.


Keywords
--------

In addition to the common :ref:`plugin <part-properties-plugin>` and
:ref:`sources <part-properties-sources>` keywords, this plugin
provides the following plugin-specific keywords:

maven-parameters
~~~~~~~~~~~~~~~~
**Type:** list of strings

Used to add additional parameters to the ``mvn package`` command line.


Environment variables
---------------------

This plugin reads the ``http_proxy`` and ``https_proxy`` variables
from the environment to configure Maven proxy access. A
comma-separated list of hosts that should not be accessed via proxy is
read from the ``no_proxy`` environment variable. The plugin writes the
proxy configuration in ``$CRAFT_PART_BUILD/.parts/.m2/settings.xml``.

This plugin will set the ``JAVA_HOME`` environment variable to the
path to the latest JDK found in the build environment.

Please refer to
`Configuring Apache Maven <https://maven.apache.org/configure.html>`_
for a list of environment variables used to configure Maven.

.. _rockcraft_maven-details-begin:

.. include:: /common/craft-parts/reference/plugins/maven_plugin.rst
:start-after: .. _maven-details-begin:
:end-before: .. _maven-details-end:

.. _rockcraft_maven-details-end:

.. include:: /common/craft-parts/reference/plugins/maven_plugin.rst
:start-after: .. _maven-details-end:
40 changes: 40 additions & 0 deletions rockcraft/plugins/ant_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2024 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""The Rockcraft Ant plugin."""
import logging

from craft_parts.plugins import ant_plugin
from overrides import override # type: ignore[reportUnknownVariableType]

from .java_common import create_usr_bin_java

logger = logging.getLogger(__name__)


class AntPlugin(ant_plugin.AntPlugin):
"""An AntPlugin plugin for Rockcraft.
This plugin extends Craft-parts' vanilla Ant plugin to properly
use and install the Java VM. Specifically:
- Do not link java executable to /bin/java
"""

@override
def _get_java_link_commands(self) -> list[str]:
"""Get the bash commands to provide /bin/java symlink."""
return create_usr_bin_java()
30 changes: 30 additions & 0 deletions rockcraft/plugins/java_common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2024 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Common functionality for Java-based plugins.
This module provides a function to create a /usr/bin/java symlink.
"""


def create_usr_bin_java() -> list[str]:
"""Get the bash commands to create /usr/bin/java symlink."""
return [
'# Find the "java" executable and make a link to it in $CRAFT_PART_INSTALL/bin/java',
"java_bin=$(find ${CRAFT_PART_INSTALL} -name java -type f -executable)",
"test -d ${CRAFT_PART_INSTALL}/usr/bin && "
"(test -f ${CRAFT_PART_INSTALL}/usr/bin/java || "
"ln -s --relative $java_bin ${CRAFT_PART_INSTALL}/usr/bin/java)",
]
40 changes: 40 additions & 0 deletions rockcraft/plugins/maven_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2024 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""The Rockcraft Maven plugin."""
import logging

from craft_parts.plugins import maven_plugin
from overrides import override # type: ignore[reportUnknownVariableType]

from .java_common import create_usr_bin_java

logger = logging.getLogger(__name__)


class MavenPlugin(maven_plugin.MavenPlugin):
"""A MavenPlugin plugin for Rockcraft.
This plugin extends Craft-parts' vanilla Maven plugin to properly
use and install the Java VM. Specifically:
- Do not link java executable to /bin/java
"""

@override
def _get_java_link_commands(self) -> list[str]:
"""Get the bash commands to provide /usr/bin/java symlink."""
return create_usr_bin_java()
9 changes: 8 additions & 1 deletion rockcraft/plugins/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import craft_parts
from craft_parts.plugins.plugins import PluginType

from .ant_plugin import AntPlugin
from .maven_plugin import MavenPlugin
from .poetry_plugin import PoetryPlugin
from .python_plugin import PythonPlugin

Expand All @@ -30,4 +32,9 @@ def register() -> None:

def get_plugins() -> dict[str, PluginType]:
"""Get a dict of Rockcraft-specific plugins."""
return {"poetry": PoetryPlugin, "python": PythonPlugin}
return {
"ant": AntPlugin,
"poetry": PoetryPlugin,
"python": PythonPlugin,
"maven": MavenPlugin,
}
22 changes: 22 additions & 0 deletions tests/spread/rockcraft/plugin-ant/rockcraft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: plugin-ant
base: bare
build-base: [email protected]

version: '0.1'
summary: A rock that bundles an Ant project.
description: A rock that bundles an Ant project.
license: GPL-3.0
platforms:
amd64:

parts:
ant-sample:
plugin: ant
source: sample
ant-build-targets: [compile, jar]
stage-packages:
- openjdk-21-jre-headless_core
- base-files_base
build-packages:
- ant
- openjdk-21-jdk-headless
28 changes: 28 additions & 0 deletions tests/spread/rockcraft/plugin-ant/sample/build.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<project>

<property name="ant.build.javac.source" value="8"/>
<property name="ant.build.javac.target" value="8"/>

<target name="clean">
<delete dir="build"/>
</target>

<target name="compile">
<mkdir dir="build/classes"/>
<javac srcdir="src" destdir="build/classes"/>
</target>

<target name="jar">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/HelloWorld.jar" basedir="build/classes">
<manifest>
<attribute name="Main-Class" value="sample.HelloWorld"/>
</manifest>
</jar>
</target>

<target name="run">
<java jar="build/jar/HelloWorld.jar" fork="true"/>
</target>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package sample;

public class HelloWorld {
public static void main(String[] args) {
System.out.println("hello world");
}
}
16 changes: 16 additions & 0 deletions tests/spread/rockcraft/plugin-ant/task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
summary: Maven plugin tests
execute: |
SCENARIO="plugin-ant"
ROCK_FILE="${SCENARIO}_0.1_amd64.rock"
IMAGE="${SCENARIO}:0.1"
# Build the rock & load it into docker
run_rockcraft pack
echo expecting ${ROCK_FILE}
test -f ${ROCK_FILE}
rockcraft.skopeo copy --insecure-policy oci-archive:${ROCK_FILE} docker-daemon:${IMAGE}
rm ${ROCK_FILE}
# Run the packaged project
docker run --rm $IMAGE exec /usr/bin/java -jar /jar/HelloWorld.jar | MATCH "hello world"
docker run --rm $IMAGE exec /bin/java -jar /jar/HelloWorld.jar | MATCH "hello world"
22 changes: 22 additions & 0 deletions tests/spread/rockcraft/plugin-maven/rockcraft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: plugin-maven
base: bare
build-base: [email protected]

version: '0.1'
summary: A rock that bundles a Maven project.
description: A rock that bundles a Maven project.
license: GPL-3.0
platforms:
amd64:

parts:
maven-sample:
plugin: maven
source: sample
maven-parameters: [ "-B" ]
stage-packages:
- openjdk-21-jre-headless_core
- base-files_base
build-packages:
- maven
- openjdk-21-jdk-headless
Loading

0 comments on commit b7ea743

Please sign in to comment.