Construyendo una tubería para entregar Graal Native Image a los usuarios finales

En este artículo, quiero describir mi experiencia en la entrega de Graal Native Image a usuarios finales de Mac OS y Linux en un comando usando Travis CI.


Cuando me encontré con este problema, sentí una falta de información sobre este tema, así que decidí describir mi experiencia aquí.


Empecemos.


Yo tengo:


  • Aplicación Java con todas las configuraciones para construir imágenes nativas.

Lo que quiero obtener:


  • Construye una imagen nativa con Travis
  • Cree distribuciones rpm y deb, así como un archivo para la versión mac
  • Vierta los paquetes recibidos en Bintray
  • Ofrezca a los usuarios la posibilidad de descargar la aplicación a través del administrador de paquetes
  • Automatice el proceso tanto como sea posible.

Vamos


Primero, crea un simple Hello world.


package release.test;

public class Application {

    public static void main(String[] args) {
        System.out.println("Hello world");
    }
}

Y agregue complementos base a pom.xml.


 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
            </plugin>
            <plugin>
                <!-- Build an executable JAR -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>release.test.Application</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>2.5.3</version>
                <configuration>
                    <tagNameFormat>${project.version}</tagNameFormat>
                </configuration>
            </plugin>
        </plugins>
    </build>

A continuación, crearé dos perfiles para construir mac y linux, respectivamente. Lo voy a utilizar maven-assembly-plugin. No obstruiré el artículo con toneladas de xml, en su lugar adjuntaré un enlace con un ejemplo completo.


Pasemos a Travis CI. Aquí es donde quiero construir una imagen nativa, empaquetarla en los paquetes correctos e implementarla.


Crearemos un archivo .travis.ymlpara describir el plan de implementación y lo llenaremos gradualmente.
Para comenzar, se verá así:


os:
 - linux
 - osx

language: java
install: true

script:
 - if [ $TRAVIS_OS_NAME == "osx" ]; then
    chmod +x ./prepare-mac.sh;
    ./prepare-mac.sh;
   fi
 - if [ $TRAVIS_OS_NAME == "linux" ]; then
    chmod +x ./prepare-linux.sh;
    ./prepare-linux.sh;
   fi

, . .


Mac OS :


#!/usr/bin/env bash
curl -OL https://github.com/oracle/graal/releases/download/vm-19.1.1/graalvm-ce-darwin-amd64-19.1.1.tar.gz
tar zxf graalvm-ce-darwin-amd64-19.1.1.tar.gz
sudo mv graalvm-ce-19.1.1 /Library/Java/JavaVirtualMachines
export PATH=/Library/Java/JavaVirtualMachines/graalvm-ce-19.1.1/Contents/Home/bin:$PATH
/Library/Java/JavaVirtualMachines/graalvm-ce-19.1.1/Contents/Home/bin/gu install native-image
mvn clean package -P mac
NAME=$(basename $(find . -type f -name 'release-test-*.jar'))
native-image -jar target/${NAME} -H:Name=release-test
mvn package -P assembly

. , GraalVM, native-image, Graal Mac. , jar, native-image , .


Linux , rpm deb :


#!/usr/bin/env bash
curl -OL https://github.com/oracle/graal/releases/download/vm-19.1.1/graalvm-ce-linux-amd64-19.1.1.tar.gz
tar zxf graalvm-ce-linux-amd64-19.1.1.tar.gz
sudo mv graalvm-ce-19.1.1 /usr/lib/jvm/
export JAVA_HOME=/usr/lib/jvm/graalvm-ce-19.1.1
export PATH=$PATH:${JAVA_HOME}/bin

mvn clean install
${JAVA_HOME}/bin/gu install native-image
NAME=$(basename $(find . -type f -name 'release-test-*.jar'))

mkdir release-deb
cd release-deb
native-image -jar ../target/${NAME} -H:Name=release-test
PACK_NAME=$(ls)
chmod +x ${PACK_NAME}
mkdir packageroot
mkdir packageroot/DEBIAN
touch packageroot/DEBIAN/control
VERSION=$(echo "${NAME%.*}" | cut -d'-' -f 3)
echo "Package: $PACK_NAME
Version: $VERSION
Architecture: amd64
Maintainer: John Doe <john@doe.com>
Description: test
" > packageroot/DEBIAN/control
cat packageroot/DEBIAN/control
mkdir -p packageroot/usr/bin
cp ${PACK_NAME} packageroot/usr/bin/
dpkg-deb -b packageroot ${PACK_NAME}-${VERSION}.deb

sudo dpkg -i ./${PACK_NAME}-${VERSION}.deb
sudo apt-get install -f

DEB_PACK=$(find . -type f -name 'release-test-*.deb')
echo ${DEB_PACK}
cp ${DEB_PACK} ../target/

cd ../target

# convert to rpm
sudo apt-get update
sudo apt-get install rpm
sudo apt-get install ruby ruby-dev rubygems build-essential
gem install --no-ri --no-rdoc fpm

fpm -t rpm -s deb ${PACK_NAME}-${VERSION}.deb

GraalVM native-image. , , .


debian . , , .


mkdir release-deb
cd release-deb
native-image -jar ../target/${NAME} -H:Name=release-test
PACK_NAME=$(ls)
chmod +x ${PACK_NAME}
mkdir packageroot
mkdir packageroot/DEBIAN
touch packageroot/DEBIAN/control
VERSION=$(echo "${NAME%.*}" | cut -d'-' -f 3)
echo "Package: $PACK_NAME
Version: $VERSION
Architecture: amd64
Maintainer: John Doe <john@doe.com>
Description: test
" > packageroot/DEBIAN/control
cat packageroot/DEBIAN/control
mkdir -p packageroot/usr/bin
cp ${PACK_NAME} packageroot/usr/bin/
dpkg-deb -b packageroot ${PACK_NAME}-${VERSION}.deb

sudo dpkg -i ./${PACK_NAME}-${VERSION}.deb
sudo apt-get install -f

DEB_PACK=$(find . -type f -name 'release-test-*.deb')
echo ${DEB_PACK}
cp ${DEB_PACK} ../target/

debian rpm. , fpm. rpm debian.


# convert to rpm
sudo apt-get update
sudo apt-get install rpm
sudo apt-get install ruby ruby-dev rubygems build-essential
gem install --no-ri --no-rdoc fpm

fpm -t rpm -s deb ${PACK_NAME}-${VERSION}.deb

before_deploy .travis.yml, .


before_deploy:
  - if [ $TRAVIS_OS_NAME == "linux" ]; then
    chmod +x ./update-version.sh;
    ./update-version.sh;
    fi

update-version.sh


#!/usr/bin/env bash

cd target

NAME=$(basename $(find . -type f -name 'release-test-*.jar'))
VERSION=$(echo "${NAME%.*}" | cut -d'-' -f 3)

cd ../

sed -i "s/template_version/$VERSION/g" deploy-deb.json
sed -i "s/template_tag/$VERSION/g" deploy-deb.json

sed -i "s/template_version/$VERSION/g" deploy-rpm.json
sed -i "s/template_tag/$VERSION/g" deploy-rpm.json

deploy-deb.json deploy-rpm.json — bintray. . , . update-version.sh json .


. bintray . generic, rpm debian bintray. , master-. mac Rest API. Rest API Bintray . linux bintray provider, Travis CI.


deploy:
  - provider: script
    skip_cleanup: true
    script:
      cd target;
      curl -X PUT -H X-GPG-PASSPHRASE:$PASSPHRASE_BINTRAY --basic -u aarrsseni:$BINTRAY_API_KEY https://api.bintray.com/content/aarrsseni/release-test/release-test/$TRAVIS_TAG/release-test-$TRAVIS_TAG.zip?publish=1
    on:
      branch: master
      condition: $TRAVIS_OS_NAME == "osx"
      tags: true
  - provider: bintray
    file: deploy-deb.json
    user: aarrsseni
    key:
      secure: your_key
    passphrase:
      secure: your_passphrase
    skip_cleanup: true
    on:
      branch: master
      condition: $TRAVIS_OS_NAME == "linux"
      tags: true
  - provider: bintray
    file: deploy-rpm.json
    user: aarrsseni
    key:
      secure: your_key
    passphrase:
      secure: your_passphrase
    skip_cleanup: true
    on:
      branch: master
      condition: $TRAVIS_OS_NAME == "linux"
      tags: true

zip , rpm deb , bintray.
rpm deb apt-get yum.


mac brew . . , . .


brew Formula. release-test.rb. zip bintray, , .


class ReleaseTest < Formula
  desc "Your desc"
  homepage "your website"
  url "https://bintray.com/aarrsseni/release-test/download_file?file_path=release-test-1.70.zip"
  sha256 "84b09c9c1c45ef0b040811be58c9f14cf8ef7237139f0a8483ccd85c6ea1bb64"

  bottle :unneeded

  def install
    libexec.install Dir["*"]
    bin.install_symlink libexec/"bin/release-test"
  end

  test do
    system "release-test"
  end
end

, .travis.yml after_deploy.


after_deploy:
 - if [ $TRAVIS_OS_NAME == "osx" ]; then
  chmod +x ./update-homebrew.sh;
  ./update-homebrew.sh;
  fi

update-homebrew.sh brew , , .


#!/usr/bin/env bash
NAME=$(basename $(find . -type f -name 'release-test-*.zip'))
echo ${NAME}
mkdir temp-homebrew

CHECKSUM=$(echo "$(shasum -a 256 target/${NAME})" | awk '{print $1;}')
echo ${CHECKSUM}

cd temp-homebrew
git clone https://github.com/aarrsseni/homebrew-test-release
cd homebrew-test-release
git remote add origin-deploy https://${GITHUB_TOKEN}@github.com/aarrsseni/homebrew-test-release.git
cd Formula

cat release-test.rb

PREV_NAME=$(grep -o 'file_path=.*$' release-test.rb | cut -c11-)
PREV_NAME=${PREV_NAME%?}

PREV_CHECKSUM_FROM_FILE=$(grep -o 'sha256.*$' release-test.rb | cut -c9-)
PREV_CHECKSUM=${PREV_CHECKSUM_FROM_FILE%?}

echo ${PREV_NAME}
echo ${PREV_CHECKSUM}

sed -i '.bak' "s/$PREV_NAME/$NAME/g" release-test.rb

sed -i '.bak' "s/$PREV_CHECKSUM/$CHECKSUM/g" release-test.rb

cat release-test.rb

git add .
git commit -m "Update formula version"
git push origin-deploy master

, mac , brew install USERNAME/REPO_NAME/TOOL_NAME, USERNAME — github, REPO_NAME — , TOOL_NAME — .


, github bintray .travis.yml .



mvn release:prepare native image mac linux, .



homebrew


All Articles