From 460d30c78a5b299188479a2c8388080fbecfd6f1 Mon Sep 17 00:00:00 2001 From: thespad Date: Mon, 20 Oct 2025 10:47:08 +0100 Subject: [PATCH 1/3] Add libjemalloc as runtime dep --- .editorconfig | 0 .github/CONTRIBUTING.md | 0 .github/FUNDING.yml | 0 .github/ISSUE_TEMPLATE/config.yml | 0 .github/ISSUE_TEMPLATE/issue.bug.yml | 0 .github/ISSUE_TEMPLATE/issue.feature.yml | 0 .github/PULL_REQUEST_TEMPLATE.md | 0 .github/workflows/call_issue_pr_tracker.yml | 0 .github/workflows/call_issues_cron.yml | 0 .github/workflows/greetings.yml | 0 .github/workflows/permissions.yml | 0 Dockerfile | 4 +++- Dockerfile.aarch64 | 4 +++- README.md | 1 + readme-vars.yml | 1 + 15 files changed, 8 insertions(+), 2 deletions(-) mode change 100755 => 100644 .editorconfig mode change 100755 => 100644 .github/CONTRIBUTING.md mode change 100755 => 100644 .github/FUNDING.yml mode change 100755 => 100644 .github/ISSUE_TEMPLATE/config.yml mode change 100755 => 100644 .github/ISSUE_TEMPLATE/issue.bug.yml mode change 100755 => 100644 .github/ISSUE_TEMPLATE/issue.feature.yml mode change 100755 => 100644 .github/PULL_REQUEST_TEMPLATE.md mode change 100755 => 100644 .github/workflows/call_issue_pr_tracker.yml mode change 100755 => 100644 .github/workflows/call_issues_cron.yml mode change 100755 => 100644 .github/workflows/greetings.yml mode change 100755 => 100644 .github/workflows/permissions.yml diff --git a/.editorconfig b/.editorconfig old mode 100755 new mode 100644 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md old mode 100755 new mode 100644 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/issue.bug.yml b/.github/ISSUE_TEMPLATE/issue.bug.yml old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/issue.feature.yml b/.github/ISSUE_TEMPLATE/issue.feature.yml old mode 100755 new mode 100644 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md old mode 100755 new mode 100644 diff --git a/.github/workflows/call_issue_pr_tracker.yml b/.github/workflows/call_issue_pr_tracker.yml old mode 100755 new mode 100644 diff --git a/.github/workflows/call_issues_cron.yml b/.github/workflows/call_issues_cron.yml old mode 100755 new mode 100644 diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml old mode 100755 new mode 100644 diff --git a/.github/workflows/permissions.yml b/.github/workflows/permissions.yml old mode 100755 new mode 100644 diff --git a/Dockerfile b/Dockerfile index 9d5187db..752e67ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,9 +25,11 @@ RUN \ apt-get update && \ apt-get install -y --no-install-recommends \ at \ - jellyfin=${JELLYFIN_RELEASE} \ + libjemalloc2 \ mesa-va-drivers \ xmlstarlet && \ + apt-get install -y --no-install-recommends \ + jellyfin=${JELLYFIN_RELEASE} && \ echo "**** cleanup ****" && \ rm -rf \ /tmp/* \ diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index bf892288..14d8a11f 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -25,11 +25,13 @@ RUN \ apt-get update && \ apt-get install -y --no-install-recommends \ at \ - jellyfin=${JELLYFIN_RELEASE} \ + libjemalloc2 \ libomxil-bellagio0 \ libomxil-bellagio-bin \ libraspberrypi0 \ xmlstarlet && \ + apt-get install -y --no-install-recommends \ + jellyfin=${JELLYFIN_RELEASE} && \ printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version && \ echo "**** cleanup ****" && \ rm -rf \ diff --git a/README.md b/README.md index ea6a25d9..a97db466 100644 --- a/README.md +++ b/README.md @@ -373,6 +373,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64 ## Versions +* **20.10.25:** - Add libjemalloc as runtime dep. * **06.10.24:** - Fix fontconfig cache path. * **13.08.24:** - Rebase to Ubuntu Noble. * **01.05.24:** - Increase verbosity of device permissions fixing. diff --git a/readme-vars.yml b/readme-vars.yml index 657a465c..0ad4bde0 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -134,6 +134,7 @@ init_diagram: | "jellyfin:latest" <- Base Images # changelog changelogs: + - {date: "20.10.25:", desc: "Add libjemalloc as runtime dep."} - {date: "06.10.24:", desc: "Fix fontconfig cache path."} - {date: "13.08.24:", desc: "Rebase to Ubuntu Noble."} - {date: "01.05.24:", desc: "Increase verbosity of device permissions fixing."} From 675d27321fa5b84a8b311f45317716a3c389241c Mon Sep 17 00:00:00 2001 From: thespad Date: Mon, 20 Oct 2025 16:13:50 +0100 Subject: [PATCH 2/3] Run builder --- Jenkinsfile | 87 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index f050785d..2f646bfe 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -208,6 +208,7 @@ pipeline { env.META_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache' + env.CITEST_IMAGETAG = 'latest' } } } @@ -233,6 +234,7 @@ pipeline { env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DEV_DOCKERHUB_IMAGE + '/tags/' env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache' + env.CITEST_IMAGETAG = 'develop' } } } @@ -258,6 +260,7 @@ pipeline { env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/pull/' + env.PULL_REQUEST env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.PR_DOCKERHUB_IMAGE + '/tags/' env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache' + env.CITEST_IMAGETAG = 'develop' } } } @@ -615,13 +618,16 @@ pipeline { echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin + if [[ "${PACKAGE_CHECK}" != "true" ]]; then + declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & + pids[$!]="$i" done - for p in $(jobs -p); do - wait "$p" || { echo "job $p failed" >&2; exit 1; } + for p in "${!pids[@]}"; do + wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; } done fi ''' @@ -681,13 +687,16 @@ pipeline { echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin + if [[ "${PACKAGE_CHECK}" != "true" ]]; then + declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & + pids[$!]="$i" done - for p in $(jobs -p); do - wait "$p" || { echo "job $p failed" >&2; exit 1; } + for p in "${!pids[@]}"; do + wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; } done fi ''' @@ -741,12 +750,14 @@ pipeline { echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin if [[ "${PACKAGE_CHECK}" != "true" ]]; then + declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} & + pids[$!]="$i" done - for p in $(jobs -p); do - wait "$p" || { echo "job $p failed" >&2; exit 1; } + for p in "${!pids[@]}"; do + wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; } done fi ''' @@ -871,7 +882,7 @@ pipeline { CI_DOCKERENV="LSIO_FIRST_PARTY=true" fi fi - docker pull ghcr.io/linuxserver/ci:latest + docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} if [ "${MULTIARCH}" == "true" ]; then docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64 docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} @@ -895,7 +906,7 @@ pipeline { -e WEB_PATH=\"${CI_WEBPATH}\" \ -e NODE_NAME=\"${NODE_NAME}\" \ -e SYFT_IMAGE_TAG=\"${CI_SYFT_IMAGE_TAG:-${SYFT_IMAGE_TAG}}\" \ - -t ghcr.io/linuxserver/ci:latest \ + -t ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} \ python3 test_build.py''' } } @@ -921,9 +932,11 @@ pipeline { CACHEIMAGE=${i} fi done - docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:latest -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} + docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:latest -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } if [ -n "${SEMVER}" ]; then - docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} + docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } fi done ''' @@ -948,20 +961,27 @@ pipeline { CACHEIMAGE=${i} fi done - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-latest -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-latest -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} + docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-latest -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } + docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-latest -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } if [ -n "${SEMVER}" ]; then - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} + docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } + docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } fi done for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do - docker buildx imagetools create -t ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:amd64-latest ${MANIFESTIMAGE}:arm64v8-latest - docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} - - docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} + docker buildx imagetools create -t ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:amd64-latest ${MANIFESTIMAGE}:arm64v8-latest || \ + { [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } + docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \ + { [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } + docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \ + { [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } if [ -n "${SEMVER}" ]; then - docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} + docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} || \ + { [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]] && exit 1; } fi done ''' @@ -979,6 +999,16 @@ pipeline { environment name: 'EXIT_STATUS', value: '' } steps { + echo "Auto-generating release notes" + sh '''if [ "$(git tag --points-at HEAD)" != "" ]; then + echo "Existing tag points to current commit, suggesting no new LS changes" + AUTO_RELEASE_NOTES="No changes" + else + AUTO_RELEASE_NOTES=$(curl -fsL -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github+json" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases/generate-notes \ + -d '{"tag_name":"'${META_TAG}'",\ + "target_commitish": "master"}' \ + | jq -r '.body' | sed 's|## What.s Changed||') + fi''' echo "Pushing New tag for current commit ${META_TAG}" sh '''curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \ -d '{"tag":"'${META_TAG}'",\ @@ -989,12 +1019,19 @@ pipeline { echo "Pushing New release for Tag" sh '''#! /bin/bash echo "Updating to ${EXT_RELEASE_CLEAN}" > releasebody.json - echo '{"tag_name":"'${META_TAG}'",\ - "target_commitish": "master",\ - "name": "'${META_TAG}'",\ - "body": "**CI Report:**\\n\\n'${CI_URL:-N/A}'\\n\\n**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**Remote Changes:**\\n\\n' > start - printf '","draft": false,"prerelease": false}' >> releasebody.json - paste -d'\\0' start releasebody.json > releasebody.json.done + jq -n \ + --arg tag_name "$META_TAG" \ + --arg target_commitish "master" \ + --arg ci_url "${CI_URL:-N/A}" \ + --arg ls_notes "$AUTO_RELEASE_NOTES" \ + --arg remote_notes "$(cat releasebody.json)" \ + '{ + "tag_name": $tag_name, + "target_commitish": $target_commitish, + "name": $tag_name, + "body": ("**CI Report:**\\n\\n" + $ci_url + "\\n\\n**LinuxServer Changes:**\\n\\n" + $ls_notes + "\\n\\n**Remote Changes:**\\n\\n" + $remote_notes), + "draft": false, + "prerelease": false }' > releasebody.json.done curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done''' } } From 992451ff2afb23b886f5b7e26244f426e1cd8a42 Mon Sep 17 00:00:00 2001 From: thespad Date: Mon, 20 Oct 2025 16:23:15 +0100 Subject: [PATCH 3/3] Increase CI delay to account for slow arm startup --- Jenkinsfile | 2 +- jenkins-vars.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2f646bfe..74439574 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -32,7 +32,7 @@ pipeline { CI_WEB='true' CI_PORT='8096' CI_SSL='false' - CI_DELAY='120' + CI_DELAY='300' CI_DOCKERENV='' CI_AUTH='' CI_WEBPATH='' diff --git a/jenkins-vars.yml b/jenkins-vars.yml index e407127d..2c4a00c2 100644 --- a/jenkins-vars.yml +++ b/jenkins-vars.yml @@ -21,7 +21,7 @@ repo_vars: - CI_WEB='true' - CI_PORT='8096' - CI_SSL='false' - - CI_DELAY='120' + - CI_DELAY='300' - CI_DOCKERENV='' - CI_AUTH='' - CI_WEBPATH=''