diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 44c5c16..c76a1aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: ARCH: ${{ matrix.ARCH }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: 'recursive' @@ -30,7 +30,7 @@ jobs: bash -ex ci/build-in-docker.sh - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: # Artifact name name: appimagetool-${{ matrix.ARCH }}.build @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Download artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 - name: Inspect directory after downloading artifacts run: ls -alFR - name: Create release and upload artifacts @@ -53,4 +53,4 @@ jobs: run: | wget -q https://github.com/TheAssassin/pyuploadtool/releases/download/continuous/pyuploadtool-x86_64.AppImage chmod +x pyuploadtool-x86_64.AppImage - ./pyuploadtool-x86_64.AppImage **/appimagetool*.AppImage* + GITHUB_CONTINUOUS_RELEASE_TYPE=stable ./pyuploadtool-x86_64.AppImage **/appimagetool*.AppImage* diff --git a/ci/build-in-docker.sh b/ci/build-in-docker.sh index 42e4283..b237214 100755 --- a/ci/build-in-docker.sh +++ b/ci/build-in-docker.sh @@ -9,19 +9,15 @@ fi case "$ARCH" in x86_64) - image_prefix=amd64 platform=linux/amd64 ;; i686) - image_prefix=i386 platform=linux/i386 ;; armhf) - image_prefix=arm32v7 platform=linux/arm/v7 ;; aarch64) - image_prefix=arm64v8 platform=linux/arm64/v8 ;; *) @@ -30,8 +26,9 @@ case "$ARCH" in ;; esac + # libassuan-static is supported only from 3.19 onwards -image="$image_prefix"/alpine:3.19 +image=alpine:3.19 repo_root="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")"/..)" @@ -62,10 +59,11 @@ docker run \ set -euxo pipefail -apk add bash git gcc g++ cmake make file desktop-file-utils wget \ +apk add bash git gcc g++ cmake make file wget \ gpgme-dev libgcrypt-dev libgcrypt-static argp-standalone zstd-dev zstd-static util-linux-static \ glib-static libassuan-static zlib-static libgpg-error-static \ - curl-dev curl-static nghttp2-static libidn2-static openssl-libs-static brotli-static c-ares-static libunistring-static + curl-dev curl-static nghttp2-static libidn2-static openssl-libs-static brotli-static c-ares-static libunistring-static \ + glib-static glib-dev autoconf automake meson # libcurl's pkg-config scripts are broken. everywhere, everytime. # these additional flags have been collected from all the .pc files whose libs are mentioned as -l in Libs.private @@ -77,7 +75,9 @@ echo "Requires.private: libcares libnghttp2 libidn2 libssl openssl libcrypto lib # in a Docker container, we can safely disable this check git config --global --add safe.directory '*' +bash -euxo pipefail /source/ci/install-static-desktop-file-validate.sh 0.28 bash -euxo pipefail /source/ci/install-static-mksquashfs.sh 4.6.1 +bash -euxo pipefail /source/ci/install-static-zsyncmake.sh 0.6.2 bash -euxo pipefail /source/ci/build.sh diff --git a/ci/build.sh b/ci/build.sh index e7b06b9..338d972 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -36,7 +36,9 @@ make install DESTDIR=AppDir find AppDir +cp "$(which desktop-file-validate)" AppDir/usr/bin cp "$(which mksquashfs)" AppDir/usr/bin +#cp "$(which zsyncmake)" AppDir/usr/bin cp "$repo_root"/resources/AppRun.sh AppDir/AppRun chmod +x AppDir/AppRun diff --git a/ci/install-static-desktop-file-validate.sh b/ci/install-static-desktop-file-validate.sh new file mode 100644 index 0000000..f64b10e --- /dev/null +++ b/ci/install-static-desktop-file-validate.sh @@ -0,0 +1,39 @@ +#! /bin/bash + +set -euxo pipefail + +if [[ "${1:-}" == "" ]]; then + echo "Usage: $0 " + exit 2 +fi + +version="$1" + +build_dir="$(mktemp -d -t desktop-file-utils-build-XXXXXX)" + +cleanup () { + if [ -d "$build_dir" ]; then + rm -rf "$build_dir" + fi +} +trap cleanup EXIT + +pushd "$build_dir" + +# apk add glib-static glib-dev autoconf automake # Moved to build-in-docker.sh + +wget -c "https://gitlab.freedesktop.org/xdg/desktop-file-utils/-/archive/"$version"/desktop-file-utils-"$version".tar.gz" +tar xf desktop-file-utils-*.tar.gz +cd desktop-file-utils-*/ + +# setting LDFLAGS as suggested in https://mesonbuild.com/Creating-Linux-binaries.html#building-and-installing +env LDFLAGS=-static meson setup build --prefer-static --default-library=static + +if [[ "${GITHUB_ACTIONS:-}" != "" ]]; then + jobs="$(nproc)" +else + jobs="$(nproc --ignore=1)" +fi + +ninja -C build -j "$jobs" -v +ninja -C build -j 1 -v install diff --git a/ci/install-static-zsyncmake.sh b/ci/install-static-zsyncmake.sh new file mode 100644 index 0000000..d4f7449 --- /dev/null +++ b/ci/install-static-zsyncmake.sh @@ -0,0 +1,38 @@ +#! /bin/bash + +set -euxo pipefail + +if [[ "${1:-}" == "" ]]; then + echo "Usage: $0 " + exit 2 +fi + +version="$1" + +build_dir="$(mktemp -d -t zsyncmake-build-XXXXXX)" + +cleanup () { + if [ -d "$build_dir" ]; then + rm -rf "$build_dir" + fi +} +trap cleanup EXIT + +pushd "$build_dir" + +wget http://zsync.moria.org.uk/download/zsync-"$version".tar.bz2 -q +tar xf zsync-*.tar.bz2 + +cd zsync-*/ + +find . -type f -exec sed -i -e 's|off_t|size_t|g' {} \; + +./configure CFLAGS=-no-pie LDFLAGS=-static --prefix=/usr --build=$(arch)-unknown-linux-gnu + +if [[ "${GITHUB_ACTIONS:-}" != "" ]]; then + jobs="$(nproc)" +else + jobs="$(nproc --ignore=1)" +fi + +make -j"$jobs" install \ No newline at end of file diff --git a/src/appimagetool.c b/src/appimagetool.c index 84c33eb..746e1c8 100644 --- a/src/appimagetool.c +++ b/src/appimagetool.c @@ -511,7 +511,7 @@ static GOptionEntry entries[] = { { "list", 'l', 0, G_OPTION_ARG_NONE, &list, "List files in SOURCE AppImage", NULL }, { "updateinformation", 'u', 0, G_OPTION_ARG_STRING, &updateinformation, "Embed update information STRING; if zsyncmake is installed, generate zsync file", NULL }, - { "guess", 'g', 0, G_OPTION_ARG_NONE, &guess_update_information, "Guess update information based on Travis CI or GitLab environment variables", NULL }, + { "guess", 'g', 0, G_OPTION_ARG_NONE, &guess_update_information, "Guess update information based on GitHub or GitLab environment variables", NULL }, { "version", 0, 0, G_OPTION_ARG_NONE, &showVersionOnly, "Show version number", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Produce verbose output", NULL }, { "sign", 's', 0, G_OPTION_ARG_NONE, &sign, "Sign with gpg[2]", NULL }, @@ -543,10 +543,34 @@ main (int argc, char *argv[]) travis_tag = getenv("TRAVIS_TAG"); char* travis_pull_request; travis_pull_request = getenv("TRAVIS_PULL_REQUEST"); + + /* Parse GitHub Actions environment variables. + * https://docs.github.com/en/actions/learn-github-actions/variables + * GITHUB_REPOSITORY: The owner and repository name. For example, octocat/Hello-World. + * GITHUB_REPOSITORY_OWNER: The repository owner's name. For example, octocat. + */ + /* https://github.com/probonopd/uploadtool */ char* github_token; github_token = getenv("GITHUB_TOKEN"); + // Construct the repository name from github_repository and github_repository_owner + // by removing the github_repository_owner from the beginning of github_repository + // and the slash that follows it + char* github_repository = getenv("GITHUB_REPOSITORY"); + char* github_repository_owner = getenv("GITHUB_REPOSITORY_OWNER"); + char* github_repository_name = NULL; + if (github_repository_owner != NULL && github_repository != NULL) { + char* owner_start = strstr(github_repository, github_repository_owner); + if (owner_start != NULL) { + owner_start += strlen(github_repository_owner); + // Skip the '/' + if (*owner_start == '/') + owner_start++; + github_repository_name = owner_start; + } + } + /* Parse GitLab CI environment variables. * https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables * echo "${CI_PROJECT_URL}/-/jobs/artifacts/${CI_COMMIT_REF_NAME}/raw/QtQuickApp-x86_64.AppImage?job=${CI_JOB_NAME}" @@ -835,7 +859,8 @@ main (int argc, char *argv[]) fprintf (stderr, "WARNING: AppStream upstream metadata is missing, please consider creating it\n"); fprintf (stderr, " in usr/share/metainfo/%s\n", application_id); fprintf (stderr, " Please see https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html#sect-Quickstart-DesktopApps\n"); - fprintf (stderr, " for more information or use the generator at http://output.jsbin.com/qoqukof.\n"); + fprintf (stderr, " for more information or use the generator at\n"); + fprintf (stderr, " https://docs.appimage.org/packaging-guide/optional/appstream.html#using-the-appstream-generator\n"); } else { fprintf (stderr, "AppStream upstream metadata found in usr/share/metainfo/%s\n", application_id); /* Use ximion's appstreamcli to make sure that desktop file and appdata match together */ @@ -915,10 +940,32 @@ main (int argc, char *argv[]) exit(1); } - /* If the user has not provided update information but we know this is a Travis CI build, - * then fill in update information based on TRAVIS_REPO_SLUG */ + /* If the user has not provided update information but we know this is a CI build, + * then fill in update information based on well-known CI environment variables */ if(guess_update_information){ - if(travis_repo_slug){ + + if(github_repository_name){ + if(!github_token) { + printf("Will not guess update information since $GITHUB_TOKEN is missing\n"); + } else { + gchar *zsyncmake_path = g_find_program_in_path ("zsyncmake"); + if(zsyncmake_path){ + char buf[1024]; + // gh-releases-zsync|probono|AppImages|latest|Subsurface-*x86_64.AppImage.zsync + int ret = snprintf(buf, "gh-releases-zsync|%s|%s|latest|%s*-%s.AppImage.zsync", github_repository_owner, github_repository_name, app_name_for_filename, arch); + if (ret < 0) { + die("snprintf error"); + } else if (ret >= sizeof(buf)) { + die("snprintf buffer overflow"); + } + updateinformation = buf; + printf("Guessing update information based on $GITHUB_REPOSITORY=%s\n", github_repository); + printf("%s\n", updateinformation); + } else { + printf("Will not guess update information since zsyncmake is missing\n"); + } + } + } else if(travis_repo_slug){ if(!github_token) { printf("Will not guess update information since $GITHUB_TOKEN is missing,\n"); if(0 != strcmp(travis_pull_request, "false")){ @@ -940,7 +987,12 @@ main (int argc, char *argv[]) channel = "latest"; } } - sprintf(buf, "gh-releases-zsync|%s|%s|%s|%s*-%s.AppImage.zsync", parts[0], parts[1], channel, app_name_for_filename, arch); + int ret = snprintf(buf, sizeof(buf), "gh-releases-zsync|%s|%s|%s|%s*-%s.AppImage.zsync", parts[0], parts[1], channel, app_name_for_filename, arch); + if (ret < 0) { + die("snprintf error"); + } else if (ret >= sizeof(buf)) { + die("snprintf buffer overflow"); + } updateinformation = buf; printf("Guessing update information based on $TRAVIS_TAG=%s and $TRAVIS_REPO_SLUG=%s\n", travis_tag, travis_repo_slug); printf("%s\n", updateinformation); @@ -953,7 +1005,12 @@ main (int argc, char *argv[]) gchar *zsyncmake_path = g_find_program_in_path ("zsyncmake"); if(zsyncmake_path){ char buf[1024]; - sprintf(buf, "zsync|%s/-/jobs/artifacts/%s/raw/%s-%s.AppImage.zsync?job=%s", CI_PROJECT_URL, CI_COMMIT_REF_NAME, app_name_for_filename, arch, CI_JOB_NAME); + int ret = snprintf(buf, sizeof(buf), "zsync|%s/-/jobs/artifacts/%s/raw/%s-%s.AppImage.zsync?job=%s", CI_PROJECT_URL, CI_COMMIT_REF_NAME, app_name_for_filename, arch, CI_JOB_NAME); + if (ret < 0) { + die("snprintf error"); + } else if (ret >= sizeof(buf)) { + die("snprintf buffer overflow"); + } updateinformation = buf; printf("Guessing update information based on $CI_COMMIT_REF_NAME=%s and $CI_JOB_NAME=%s\n", CI_COMMIT_REF_NAME, CI_JOB_NAME); printf("%s\n", updateinformation);