From 9768314a12b38be5cea4390a764cb59f2f96e573 Mon Sep 17 00:00:00 2001 From: Alexander Braverman Masis Date: Wed, 18 Mar 2020 17:44:33 +0200 Subject: [PATCH] Update AppImage building process (#1695) --- .github/workflows/packaging.yml | 64 +++- appimage.yml | 35 --- appimage/Dockerfile | 24 ++ appimage/appimage.yml | 34 +++ appimage/pkg2appimage | 470 ++++++++++++++++++++++++++++++ appimage/pkg2appimage-with-docker | 107 +++++++ rpm/linchpin.json | 2 +- 7 files changed, 693 insertions(+), 43 deletions(-) delete mode 100644 appimage.yml create mode 100644 appimage/Dockerfile create mode 100644 appimage/appimage.yml create mode 100755 appimage/pkg2appimage create mode 100755 appimage/pkg2appimage-with-docker diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index e043f0316..5ab47e851 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -21,8 +21,10 @@ jobs: - run: pip install --user rpmvenv - run: rpmdev-setuptree - run: python3 setup.py sdist -d "${HOME}/rpmbuild/SOURCES" - - run: | + - id: rpm + run: | version="$(cat linchpin/version.py | awk -F "'" '{print $2}' | head -n1)" + echo "::set-output name=version::${version}" mv "${HOME}/rpmbuild/SOURCES/linchpin-${version}.tar.gz" "${HOME}/rpmbuild/SOURCES/v${version}.tar.gz" "${HOME}/.local/bin/rpmvenv" rpm/linchpin.json --core_version="${version}" --verbose --spec | tee "${HOME}/rpmbuild/SPECS/linchpin.spec" sed -i -e "s#^Requires: .*#Requires: git, python3.6#g" \ @@ -45,13 +47,17 @@ jobs: -e '/^%post/i unlink %{buildroot}/opt/linchpin/lib64 || true' \ -e '/^%post/i ln -s /opt/linchpin/lib %{buildroot}/opt/linchpin/lib64 || true' \ "${HOME}/rpmbuild/SPECS/linchpin.spec" - - run: | + - id: result + run: | rpmbuild -ba "${HOME}/rpmbuild/SPECS/linchpin.spec" - mv ~/rpmbuild/RPMS/x86_64/*.x86_64.rpm linchpin.fc31.x86_64.rpm + rpm_path="$(readlink -f $HOME/rpmbuild/RPMS/x86_64/*.rpm)" + rpm_name="$(basename $rpm_path)" + mv $rpm_path ./ + echo "::set-output name=name::${rpm_name}" - uses: actions/upload-artifact@v1 with: - name: linchpin.fc31.x86_64.rpm - path: linchpin.fc31.x86_64.rpm + name: ${{steps.result.outputs.name}} + path: ${{steps.result.outputs.name}} - name: Upload Release Asset if: github.event_name == 'release' id: upload-release-asset @@ -60,6 +66,50 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} - asset_path: linchpin.fc31.x86_64.rpm - asset_name: linchpin.fc31.x86_64.rpm + asset_path: ${{steps.result.outputs.name}} + asset_name: ${{steps.result.outputs.name}} asset_content_type: application/rpm + appimage: + name: Build AppImage + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Cache Docker image + id: cache + uses: actions/cache@v1 + with: + path: appimage + key: ${{ hashFiles('appimage/Dockerfile') }} + - name: Build Docker image + if: steps.cache.outputs['cache-hit'] != 'true' + run: | + docker build -t appimage-build appimage + docker save appimage-build > appimage/buildimage.tar + - name: Load Docker image + if: steps.cache.outputs['cache-hit'] == 'true' + run: | + docker load < appimage/buildimage.tar + - id: version + run: | + version="$(cat linchpin/version.py | awk -F "'" '{print $2}' | head -n1)" + echo "::set-output name=version::${version}" + - id: appimage + run: | + cd appimage + ./pkg2appimage-with-docker appimage.yml 2>&1 + - uses: actions/upload-artifact@v1 + with: + name: Linchpin-${{ steps.version.outputs.version }}.glibc2.17-x86_64.AppImage + path: appimage/out/Linchpin-${{ steps.version.outputs.version }}.glibc2.17-x86_64.AppImage + - name: Upload Release Asset + if: github.event_name == 'release' + id: upload-release-asset + uses: actions/upload-release-asset@v1.0.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: Linchpin-${{ steps.version.outputs.version }}.glibc2.17-x86_64.AppImage + asset_name: Linchpin-${{ steps.version.outputs.version }}.glibc2.17-x86_64.AppImage + asset_content_type: application/appimage + diff --git a/appimage.yml b/appimage.yml deleted file mode 100644 index 339cfbaaf..000000000 --- a/appimage.yml +++ /dev/null @@ -1,35 +0,0 @@ -app: Linchpin -ingredients: - dist: trusty - sources: - - deb http://us.archive.ubuntu.com/ubuntu/ disco trusty-updates disco-security main universe - - deb http://us.archive.ubuntu.com/ubuntu/ disco-updates main universe - - deb http://us.archive.ubuntu.com/ubuntu/ disco-security main universe - packages: - - virtualenv - -script: - - virtualenv -p /usr/bin/python2.7 usr - - ./usr/bin/pip2 install linchpin - - ./usr/bin/pip2 install linchpin[libvirt] - - usr/bin/pip2 freeze | grep "linchpin" | cut -d "=" -f 3 > ../VERSION - - virtualenv --relocatable usr - - cat > linchpin.desktop <<\EOF - - [Desktop Entry] - - Type=Application - - Name=Linchpin - - Comment=Provisioning - - Icon=linchpin - - Exec=linchpin - - Terminal=true - - Categories=Application;Development; - - StartupWMClass=linchpin - - MimeType=text/x-python3;text/x-python3; - - EOF - - cat > AppRun <<\EOF - - #!/bin/bash - - HERE="$(dirname "$(readlink -f "${0}")")" - - exec "${HERE}/usr/bin/python2" "${HERE}/usr/bin/linchpin" "$@" - - EOF - - chmod a+x ./AppRun - - wget -nc -q -O linchpin.png https://linchpinjobs.com/img/linchpinjobs_logo.png diff --git a/appimage/Dockerfile b/appimage/Dockerfile new file mode 100644 index 000000000..78f30b6e5 --- /dev/null +++ b/appimage/Dockerfile @@ -0,0 +1,24 @@ +# Beware: only meant for use with pkg2appimage-with-docker + +FROM ubuntu:xenial + +MAINTAINER "TheAssassin " + +ENV DEBIAN_FRONTEND=noninteractive \ + DOCKER_BUILD=1 + +RUN sed -i 's/archive.ubuntu.com/ftp.fau.de/g' /etc/apt/sources.list ;\ + echo "deb http://ppa.launchpad.net/deadsnakes/ppa/ubuntu xenial main" >> /etc/apt/sources.list ;\ + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F23C5A6CF475977595C89F51BA6932366A755776 ;\ + apt-get update +RUN apt-get install -y python3.7 python3.7-dev python3.7-venv python3.7-distutils ;\ + python3.7 -m ensurepip --default-pip ;\ + python3.7 -m pip install --upgrade pip setuptools wheel virtualenv +RUN apt-get install -y apt-transport-https libcurl3-gnutls libarchive13 wget desktop-file-utils aria2 gnupg2 build-essential file libglib2.0-bin git sudo +RUN apt-get install -y pkg-config libvirt-dev +RUN apt-get install -y fuse || true +RUN install -m 0777 -d /workspace + +RUN adduser --system --uid 1000 test + +WORKDIR /workspace diff --git a/appimage/appimage.yml b/appimage/appimage.yml new file mode 100644 index 000000000..f2bec18ff --- /dev/null +++ b/appimage/appimage.yml @@ -0,0 +1,34 @@ +app: Linchpin +binpatch: true +ingredients: + dist: xenial + sources: + - deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe + - deb http://ppa.launchpad.net/deadsnakes/ppa/ubuntu xenial main + packages: + - python3.7 +script: + - wget -nc -q -O linchpin.png https://linchpinjobs.com/img/linchpinjobs_logo.png + - virtualenv usr -p $(which python3.7) --always-copy + - ./usr/bin/pip3 install linchpin gitdb2==3.0.1 gitdb==0.6.4 + - ./usr/bin/pip3 install linchpin[libvirt] + - rm -rf usr/lib/python3/dist-packages/ + - ln -s ../python3.7/site-packages/ usr/lib/python3/dist-packages + - cat > usr/bin/linchpin-wrapper <<\EOF + - HERE="$(dirname "$(readlink -f "${0}")")" + - cd $OWD + - "${HERE}/bin/python3" "${HERE}/bin/linchpin" "$@" + - EOF + - cat > linchpin.desktop <<\EOF + - [Desktop Entry] + - Type=Application + - Name=Linchpin + - Comment=Provisioning + - Icon=linchpin + - Exec=bash linchpin-wrapper + - Terminal=true + - Categories=Application;Development; + - StartupWMClass=linchpin + - MimeType=text/x-python3;text/x-python3; + - EOF + - usr/bin/pip3 freeze | grep "linchpin" | cut -d "=" -f 3 >> ../VERSION diff --git a/appimage/pkg2appimage b/appimage/pkg2appimage new file mode 100755 index 000000000..ea37dba5b --- /dev/null +++ b/appimage/pkg2appimage @@ -0,0 +1,470 @@ +#!/usr/bin/env bash + +# env + +HERE="$(dirname "$(readlink -f "${0}")")" + +# Use privately bundled apt-get and dpkg-deb if available; can be got on trusty using +# apt download apt libapt-pkg4.12 libbz2-1.0 liblzma5 multiarch-support zlib1g dpkg +if [ -e "${HERE}/libunionpreload.so" ] ; then + export UNION_PRELOAD="${HERE}" + export LD_PRELOAD="${HERE}/libunionpreload.so" + export PATH="${HERE}"/usr/bin/:"${HERE}"/usr/sbin/:"${HERE}"/usr/games/:"${HERE}"/bin/:"${HERE}"/sbin/:"${PATH}" + export LD_LIBRARY_PATH="${HERE}"/usr/lib/:"${HERE}"/usr/lib/i386-linux-gnu/:"${HERE}"/usr/lib/x86_64-linux-gnu/:"${HERE}"/usr/lib32/:"${HERE}"/usr/lib64/:"${HERE}"/lib/:"${HERE}"/lib/i386-linux-gnu/:"${HERE}"/lib/x86_64-linux-gnu/:"${HERE}"/lib32/:"${HERE}"/lib64/:"${LD_LIBRARY_PATH}" + export XDG_DATA_DIRS="${HERE}"/usr/share/:"${XDG_DATA_DIRS}" +fi + +# Specify a certain commit if you do not want to use master +# by using: +# export PKG2AICOMMIT= +if [ -z "$PKG2AICOMMIT" ] ; then + PKG2AICOMMIT=master +fi + +usage() { + if [ -z "$APPIMAGE" ] ; then + MYSELF="$0" + else + MYSELF="$APPIMAGE" + fi + echo "usage:" + echo " $MYSELF [--no-di] META-NAME|YAMLFILE" + echo "" + echo "options:" + echo " --di enable legacy desktop integration (unsupported)" + exit 1 +} + +if [ $# -eq 0 ] || [ "x${!#}" = "x--di" ] ; then + usage +fi +if [ $# -eq 2 ] && [ "x$1" != "x--di" ] ; then + usage +fi + +if [ "x$1" = "x--di" ] ; then + ENABLE_DI="yes" +else + ENABLE_DI="no" +fi + +# Halt on errors +set -e +set -x + +# Check dependencies +which wget >/dev/null 2>&1 || ( echo wget missing && exit 1 ) +which grep >/dev/null 2>&1 || ( echo grep missing && exit 1 ) +which sed >/dev/null 2>&1 || ( echo sed missing && exit 1 ) +which cut >/dev/null 2>&1 || ( echo cut missing && exit 1 ) +which file >/dev/null 2>&1 || ( echo file missing && exit 1 ) +which desktop-file-validate >/dev/null 2>&1 || ( echo desktop-file-validate missing && exit 1 ) + +# If the yaml file doesn't exist locally, get it from GitHub +if [ ! -f "${!#}" ] ; then + YAMLFILE=/tmp/_recipe.yml + rm -f "$YAMLFILE" + wget -q "https://github.com/AppImage/AppImages/raw/${PKG2AICOMMIT}/recipes/${!#}.yml" -O "$YAMLFILE" +else + YAMLFILE=$(readlink -f "${!#}") +fi + +# Lightweight bash-only dpkg-scanpackages replacement +scanpackages() { + for deb in *.deb ; do + dpkg -I $deb | sed 's/^ *//g' | grep -i -E '(package|version|installed-size|architecture|depends|priority):' + echo "Filename: $(readlink -f $deb)" + echo "MD5sum: $(md5sum -b $deb | cut -d' ' -f1)" + echo "SHA1: $(sha1sum -b $deb | cut -d' ' -f1)" + echo "SHA256: $(sha256sum -b $deb | cut -d' ' -f1)" + echo + done +} + +# Function to parse yaml +# https://gist.github.com/epiloque/8cf512c6d64641bde388 +# based on https://gist.github.com/pkuczynski/8665367 +parse_yaml() { + local prefix=$2 + local s + local w + local fs + s='[[:blank:]]*' + w='[a-zA-Z0-9_]*' + fs="$(echo @|tr @ '\034')" + sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" | + awk -F"$fs" '{ + indent = length($1)/2; + vname[indent] = $2; + for (i in vname) {if (i > indent) {delete vname[i]}} + if (length($3) > 0) { + vn=""; for (i=0; i/dev/null || true + generate_status + + # Some packages depend on packages which we do not want to bundle, + # in addition to the global excludes defined in excludedeblist. + # Use + # ingredients: + # exclude: + # - packagename + if [ ! -z "${_ingredients_exclude[0]}" ] ; then + for PACKAGE in "${_ingredients_exclude[@]}" ; do + printf "Package: $PACKAGE\nStatus: install ok installed\nArchitecture: all\nVersion: 9:999.999.999\n\n" >> status + done + fi + + # Some packages depend on an exact version of a dependency to be installed. + # Use + # ingredients: + # pretend: + # - packagename version_to_be_pretended + if [ ! -z "${_ingredients_pretend[0]}" ] ; then + for PRETEND in "${_ingredients_pretend[@]}" ; do + P_PKG=$(echo "$PRETEND" | cut -d " " -f 1) + P_VER=$(echo "$PRETEND" | cut -d " " -f 2) + cat status | tr '\n' '@' | sed -e 's|@@|\n\n|g' | sed -e 's|Package: '"$P_PKG"'@Status: install ok installed@Architecture: all@Version: 9:999.999.999|Package: '"$P_PKG"'@Status: install ok installed@Architecture: all@Version: '"$P_VER"'|g' | sed -e 's|@|\n|g' > status.temp + mv status.temp status + done + fi + + if [ -e sources.list ] ; then + rm sources.list + fi + for SOURCE in "${_ingredients_sources[@]}" ; do + echo "${SOURCE}" >> sources.list + done + for PPA in "${_ingredients_ppas[@]}" ; do + echo "deb http://ppa.launchpad.net/${PPA}/ubuntu ${_ingredients_dist} main" >> sources.list + done + for DEBFILE in "${_ingredients_debs[@]}" ; do + cp ${DEBFILE} . + done + # Use libcurl-slim to reduce AppImage size, thanks darealshinji + # Not really compiled on xenial but CentOS 6, https://github.com/AppImage/AppImages/issues/187 + # echo "deb http://ppa.launchpad.net/djcj/libcurl-slim/ubuntu xenial main" >> sources.list + # Use gnutls-patched to have libgnutls look in various distributions' places for certificates, + # https://github.com/darealshinji/vlc-AppImage/issues/1#issuecomment-321041496 + # echo "deb http://ppa.launchpad.net/djcj/gnutls-patched/ubuntu ${_ingredients_dist} main" >> sources.list + ### echo "deb http://ppa.launchpad.net/djcj/gnutls-patched/ubuntu trusty main" >> sources.list # https://github.com/AppImage/pkg2appimage/issues/345 +fi + +if [ ! -z "${_ingredients_script[0]}" ] ; then + # Execute extra steps defined in recipe + shell_execute $YAMLFILE _ingredients_script +fi + +if [ ! -z "${_ingredients_dist}" ] ; then + # Some projects provide raw .deb files without a repository + # hence we create our own local repository as part of + # the AppImage creation process in order to "install" + # the package using apt-get as normal + if [ ! -z "${_ingredients_debs[0]}" ] ; then + for DEB in "${_ingredients_debs[@]}" ; do + if [ ! -f $(basename "$DEB") ] ; then + wget -c $DEB + fi + done + fi + scanpackages | gzip -9c > Packages.gz + echo "deb file:$(readlink -e $PWD) ./" >> sources.list + + INSTALL=$LOWERAPP + if [ ! -z "${_ingredients_package}" ] ; then + INSTALL="${_ingredients_package}" + fi + if [ ! -z "${_ingredients_packages}" ] ; then + INSTALL="" + fi + + # If packages are specifically listed, only install these, not a package with the name of the app + if [ ! -z "${_ingredients_packages[0]}" ] ; then + INSTALL=${_ingredients_packages[@]} + fi + + apt-get -o Acquire::AllowInsecureRepositories=true -o Acquire::Languages="none" -o Acquire::AllowDowngradeToInsecureRepositories=true $OPTIONS update || true + URLS=$(apt-get -o Apt::Get::AllowUnauthenticated=true $OPTIONS -y install --print-uris $INSTALL | cut -d "'" -f 2 | grep -e '^http') || true + apt-get -o Apt::Get::AllowUnauthenticated=true $OPTIONS -y install --print-uris $INSTALL | cut -d "'" -f 2 | grep -e '^http' > /tmp/packages + if which aria2c &>/dev/null; then + dltool=aria2c + else + dltool=wget + fi + $dltool -c -i /tmp/packages +fi + +if [ ! -z "${_ingredients_post_script[0]}" ] ; then + # Execute extra steps defined in recipe + shell_execute $YAMLFILE _ingredients_post_script +fi + +mkdir -p ./$APP.AppDir/ +cd ./$APP.AppDir/ + +mkdir -p usr/bin usr/lib +find ../*.deb -exec dpkg-deb -X {} . \; || true + +unset LD_PRELOAD + +# Try to copy icons to standard locations where appimaged can pick them up +mkdir -p usr/share/icons/hicolor/{22x22,24x24,32x32,48x48,64x64,128x128,256x256,512x512}/apps/ +find . -path *icons* -path *22* -name "*$LOWERAPP*" -exec cp {} usr/share/icons/hicolor/22x22/apps/ \; || true +find . -path *icons* -path *24* -name "*$LOWERAPP*" -exec cp {} usr/share/icons/hicolor/24x24/apps/ \; || true +find . -path *icons* -path *32* -name "*$LOWERAPP*" -exec cp {} usr/share/icons/hicolor/32x32/apps/ \; || true +find . -path *icons* -path *48* -name "*$LOWERAPP*" -exec cp {} usr/share/icons/hicolor/48x48/apps/ \; || true +find . -path *icons* -path *64* -name "*$LOWERAPP*" -exec cp {} usr/share/icons/hicolor/64x64/apps/ \; || true +find . -path *icons* -path *128* -name "*$LOWERAPP*" -exec cp {} usr/share/icons/hicolor/128x128/apps/ \; || true +find . -path *icons* -path *256* -name "*$LOWERAPP*" -exec cp {} usr/share/icons/hicolor/256x256/apps/ \; || true +find . -path *icons* -path *512* -name "*$LOWERAPP*" -exec cp {} usr/share/icons/hicolor/512x512/apps/ \; || true + +get_icon + +if [ -z "${_union}" ] ; then + get_apprun +else +cat > AppRun <<\EOF +#!/bin/sh +HERE="$(dirname "$(readlink -f "${0}")")" +export UNION_PRELOAD="${HERE}" +export LD_PRELOAD="${HERE}/libunionpreload.so" +export PATH="${HERE}"/usr/bin/:"${HERE}"/usr/sbin/:"${HERE}"/usr/games/:"${HERE}"/bin/:"${HERE}"/sbin/:"${PATH}" +export LD_LIBRARY_PATH="${HERE}"/usr/lib/:"${HERE}"/usr/lib/i386-linux-gnu/:"${HERE}"/usr/lib/x86_64-linux-gnu/:"${HERE}"/usr/lib32/:"${HERE}"/usr/lib64/:"${HERE}"/lib/:"${HERE}"/lib/i386-linux-gnu/:"${HERE}"/lib/x86_64-linux-gnu/:"${HERE}"/lib32/:"${HERE}"/lib64/:"${LD_LIBRARY_PATH}" +export PYTHONPATH="${HERE}"/usr/share/pyshared/:"${PYTHONPATH}" +export PYTHONHOME="${HERE}"/usr/ +export XDG_DATA_DIRS="${HERE}"/usr/share/:"${XDG_DATA_DIRS}" +export PERLLIB="${HERE}"/usr/share/perl5/:"${HERE}"/usr/lib/perl5/:"${PERLLIB}" +export GSETTINGS_SCHEMA_DIR="${HERE}"/usr/share/glib-2.0/schemas/:"${GSETTINGS_SCHEMA_DIR}" +export QT_PLUGIN_PATH="${HERE}"/usr/lib/qt4/plugins/:"${HERE}"/usr/lib/i386-linux-gnu/qt4/plugins/:"${HERE}"/usr/lib/x86_64-linux-gnu/qt4/plugins/:"${HERE}"/usr/lib32/qt4/plugins/:"${HERE}"/usr/lib64/qt4/plugins/:"${HERE}"/usr/lib/qt5/plugins/:"${HERE}"/usr/lib/i386-linux-gnu/qt5/plugins/:"${HERE}"/usr/lib/x86_64-linux-gnu/qt5/plugins/:"${HERE}"/usr/lib32/qt5/plugins/:"${HERE}"/usr/lib64/qt5/plugins/:"${QT_PLUGIN_PATH}" +EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2- | sed -e 's|%.||g') +exec ${EXEC} "$@" +EOF +chmod a+x AppRun +fi + +get_desktop + +# Prevent Qt from loading plugins from the system +unset QTPATH +QTPATH=$(find usr/lib -type d -name qt4 -or -name qt5 | sed -e 's|usr/|../|g') +if [ ! -z $QTPATH ] ; then +cat > usr/bin/qt.conf < temp \; + # Remove all absolute paths + sed -i -E 's|target=\"\/(.*\/)([a-z0-9].*?)>|target=\"\2>|g' temp + SONAMES=$(cat temp | cut -d '"' -f 4 | grep ".so" || true) + if [ "" != "$SONAMES" ] ; then + for SONAME in $SONAMES; do + find . -name "$SONAME" -exec mv {} usr/lib \; + done + fi + rm temp + PATH_OF_THE_EXE="usr/lib/mono/exe" + mkdir -p "$PATH_OF_THE_EXE" + # Force all dll files into PATH_OF_THE_EXE (or MONO_PATH which we would have to set) + find . -name "*.dll" -and -not -name "mscorlib.dll" -exec mv {} "$PATH_OF_THE_EXE" \; + # Edit all config files in place to remove absolute paths + find . -name "*.dll.config" -exec sed -i -E 's|target=\"\/(.*\/)([a-z0-9].*?)>|target=\"\2>|g' {} \; + # Force all config files into the PATH_OF_THE_EXE (or MONO_PATH which we would have to set) + find . -name "*.dll.config" -exec mv {} "$PATH_OF_THE_EXE" \; + # Remove gac, we are not using it since it is convoluted + rm -rf usr/lib/mono/gac/ +fi + +if [ -d "./usr/lib/x86_64-linux-gnu/gstreamer-1.0/" ] ; then + mv ./usr/lib/x86_64-linux-gnu/gstreamer-1.0/* ./usr/lib/x86_64-linux-gnu/ + rm -r ./usr/lib/x86_64-linux-gnu/gstreamer-1.0 +fi + +if [ -d "./usr/lib/x86_64-linux-gnu/pulseaudio/" ] ; then + mv ./usr/lib/x86_64-linux-gnu/pulseaudio/* ./usr/lib/x86_64-linux-gnu/ + rm -r ./usr/lib/x86_64-linux-gnu/pulseaudio +fi + +# Execute extra steps defined in recipe +if [ ! -z "${_script}" ] ; then + shell_execute $YAMLFILE _script +fi + +DESKTOP=$(find . -name '*.desktop' | sort | head -n 1) + +# desktop-file-validate complains about missing trailing semicolons for some +# keys although the format definition says that they are optional +fix_desktop "$DESKTOP" + +# Some non-distribution provided applications have an absolute +# path in the Exec= line which we remove for relocateability +if [ -z "$DESKTOP" ] ; then + echo "desktop file not found, aborting" + exit 1 +else + desktop-file-validate "$DESKTOP" || exit 1 + ORIG=$(grep -o "^Exec=.*$" "${DESKTOP}" | head -n 1| cut -d " " -f 1) + REPL=$(basename $(grep -o "^Exec=.*$" "${DESKTOP}" | head -n 1 | cut -d " " -f 1 | sed -e 's|Exec=||g')) + sed -i -e 's|'"${ORIG}"'|Exec='"${REPL}"'|g' "${DESKTOP}" +fi + +# Compile GLib schemas if the subdirectory is present in the AppImage +# AppRun has to export GSETTINGS_SCHEMA_DIR for this to work +if [ -d usr/share/glib-2.0/schemas/ ] ; then + ( cd usr/share/glib-2.0/schemas/ ; glib-compile-schemas . ) +fi + +if [ -f ../VERSION ] ; then + VERSION=$(cat ../VERSION) +else + get_version || true +fi + +# patch_usr +# Patching only the executable files seems not to be enough for some apps +if [ ! -z "${_binpatch}" ] ; then + find usr/ -type f -exec sed -i -e 's|/usr|././|g' {} \; + find usr/ -type f -exec sed -i -e 's@././/bin/env@/usr/bin/env@g' {} \; +fi + +# Don't suffer from NIH; use LD_PRELOAD to override calls to /usr paths +if [ ! -z "${_union}" ] ; then + mkdir -p usr/src/ + wget -q "https://raw.githubusercontent.com/mikix/deb2snap/master/src/preload.c" -O - | \ + sed -e 's|SNAPPY|UNION|g' | sed -e 's|SNAPP|UNION|g' | sed -e 's|SNAP|UNION|g' | \ + sed -e 's|snappy|union|g' > usr/src/libunionpreload.c + gcc -shared -fPIC usr/src/libunionpreload.c -o libunionpreload.so -ldl -DUNION_LIBNAME=\"libunionpreload.so\" + strip libunionpreload.so +fi + +delete_blacklisted + +if [ "$ENABLE_DI" = "yes" ] ; then + get_desktopintegration $LOWERAPP +fi + +# Fix desktop files that have file endings for icons +sed -i -e 's|\.png||g' *.desktop || true +sed -i -e 's|\.svg||g' *.desktop || true +sed -i -e 's|\.svgz||g' *.desktop || true +sed -i -e 's|\.xpm||g' *.desktop || true + +# Setting PYTHONHOME instead +# Fix Python imports, +# https://github.com/AppImage/AppImages/issues/172 +# SITECUSTOMIZEFILES=$(find . -name "sitecustomize.py") +# for SITECUSTOMIZEFILE in $SITECUSTOMIZEFILES ; do +# rm $SITECUSTOMIZEFILE # Remove symlinks, replace by files +# cat > $SITECUSTOMIZEFILE <<\EOF +# import sys,os +# if sys.version_info[0] < 3: +# prefix = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(sys.path[0])))) +# sys.path = [ prefix+s for s in sys.path if not s.startswith(prefix) ] +# EOF +# done + +# Execute extra steps defined in recipe +if [ ! -z "${_post_script[0]}" ] ; then + shell_execute $YAMLFILE _post_script +fi + +# Go out of AppImage +cd .. + +generate_type2_appimage +ls -lh ../out/*.AppImage diff --git a/appimage/pkg2appimage-with-docker b/appimage/pkg2appimage-with-docker new file mode 100755 index 000000000..f494dacb5 --- /dev/null +++ b/appimage/pkg2appimage-with-docker @@ -0,0 +1,107 @@ +#! /bin/bash + +set -e + +log() { + (echo -e "\e[91m\e[1m$*\e[0m") +} + +cleanup() { + if [ "$containerid" == "" ]; then + return 0 + fi + + if [ "$1" == "error" ]; then + log "error occurred, cleaning up..." + elif [ "$1" != "" ]; then + log "$1 received, please wait a few seconds for cleaning up..." + else + log "cleaning up..." + fi + + docker ps -a | grep -q $containerid && docker rm -f $containerid +} + +trap "cleanup SIGINT" SIGINT +trap "cleanup SIGTERM" SIGTERM +trap "cleanup error" 0 +trap "cleanup" EXIT + +CACHE=0 +RECIPE="" +ARGS="" + +for var in $@; do + case "$1" in + -c|--cache) + if [ $CACHE -ne 0 ]; then + log "warning: caching already enabled" + fi + CACHE=1 + ;; + *) + if [ "$RECIPE" != "" ]; then + log "warning: ignoring argument: $1" + else + RECIPE="$1" + fi + ;; + esac + shift +done + +if [ "$RECIPE" == "" ]; then + log "usage: $0 [-c] name.yml" + log "" + log "\t-c, --cache\tEnable pkg2appimage's caching by mounting the build cache directory into the container" + exit 1 +fi + +if [ $(basename $RECIPE .yml) == "$RECIPE" ]; then + RECIPE="$RECIPE.yml" +fi + + +if [ ! -f $RECIPE ]; then + if [ -f recipes/"$RECIPE" ]; then + RECIPE=recipes/"$RECIPE" + else + log "error: no such file or directory: $RECIPE" + exit 1 + fi +fi + +if [ $CACHE -ne 0 ]; then + recipe_name=$(basename "$RECIPE" .yml) + mkdir -p "$recipe_name" + ARGS="-v $(readlink -f $recipe_name):/workspace/$recipe_name" +fi + +log "Building $RECIPE in a container..." + +randstr=$(openssl rand -hex 8) +containerid=appimage-build-$randstr +imageid=appimage-build + +log "Building Docker container" +(set -xe; docker build -t $imageid .) + +log "Create volume" +docker volume rm target || true +set -xe +tar -cC "$(dirname $(readlink -f $RECIPE))" . | docker run -i --rm -v target:/target busybox tar -xC /target + +log "Running container" +set -xe +{ + docker run \ + --name $containerid \ + --device /dev/fuse:/dev/fuse1 \ + --security-opt apparmor:unconfined \ + --privileged \ + --user $(id -u):$(id -g) \ + -v target:/workspace \ + $imageid \ + ./pkg2appimage $RECIPE + docker cp $containerid:/workspace/out/ out + } || cleanup error diff --git a/rpm/linchpin.json b/rpm/linchpin.json index 24025c5d1..ff2b6ecca 100644 --- a/rpm/linchpin.json +++ b/rpm/linchpin.json @@ -12,7 +12,7 @@ "license": "GPLv3+", "name": "linchpin", "summary": "Ansible based multicloud orchestrator", - "release": "2%{?dist}", + "release": "1", "url": "https://linchpin.readthedocs.io", "requires": [ "python3-lxml",