From 6de7680a2f8677f3d16c5f4c9817924cabab1471 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:41:01 -0400 Subject: [PATCH 01/19] Update Dockerfile --- Dockerfile | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index 38312b7..a529dc9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ # syntax=docker/dockerfile:1 -FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.17 +# update to alpine 3.18 from archived linuxserver/docker-cops version +FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.18 # set version label ARG BUILD_DATE @@ -11,36 +12,40 @@ LABEL maintainer="chbmb" RUN \ echo "**** install runtime packages ****" && \ + # update to PHP 8.2 from archived linuxserver/docker-cops version apk add --no-cache --upgrade \ - php81-ctype \ - php81-dom \ - php81-gd \ - php81-intl \ - php81-opcache \ - php81-phar \ - php81-pdo_sqlite \ - php81-zip && \ + # libxml2 \ + php82-dom \ + php82-gd \ + php82-intl \ + # php82-json \ + php82-mbstring \ + php82-pdo_sqlite \ + php82-sqlite3 \ + php82-xml \ + php82-xmlwriter \ + php82-zip && \ + echo "**** configure php-fpm to pass env vars ****" && \ + sed -E -i 's/^;?clear_env ?=.*$/clear_env = no/g' /etc/php82/php-fpm.d/www.conf && \ + grep -qxF 'clear_env = no' /etc/php82/php-fpm.d/www.conf || echo 'clear_env = no' >> /etc/php82/php-fpm.d/www.conf && \ + echo "env[PATH] = /usr/local/bin:/usr/bin:/bin" >> /etc/php82/php-fpm.conf && \ echo "**** install cops ****" && \ - curl \ - -sS https://getcomposer.org/installer \ - | php -- --install-dir=/usr/bin --filename=composer --version=1.10.26 && \ - composer \ - global require "fxp/composer-asset-plugin:~1.1" && \ + # use fork mikespub-org/seblucas-cops for PHP 8.x if [ -z ${COPS_RELEASE+x} ]; then \ - COPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/seblucas/cops/releases/latest" \ + COPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/mikespub-org/seblucas-cops/releases/latest" \ | awk '/tag_name/{print $4;exit}' FS='[""]'); \ fi && \ curl -o \ /tmp/cops.tar.gz -L \ - "https://github.com/seblucas/cops/archive/${COPS_RELEASE}.tar.gz" && \ + "https://github.com/mikespub-org/seblucas-cops/archive/${COPS_RELEASE}.tar.gz" && \ mkdir -p \ /app/www/public && \ tar xf /tmp/cops.tar.gz -C \ /app/www/public --strip-components=1 && \ cd /app/www/public && \ + # use standard composer 2.x now, no need to install older 1.x version composer \ install --no-dev --optimize-autoloader && \ - sed -i 's|^[[:space:]]*return[[:space:]]@create_function[[:space:]]'\(''\''\$it'\'',[[:space:]]\$func'\)';| return function \(\$it\) use \(\$func\) \{\n return eval\(\$func\);\n \};|' vendor/seblucas/dot-php/doT.php && \ echo "**** cleanup ****" && \ rm -rf \ /root/.composer \ From c2490c9ed3bb923e826260fd9af28714482b2897 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:42:14 -0400 Subject: [PATCH 02/19] Update Dockerfile.aarch64 --- Dockerfile.aarch64 | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index 9b647ff..a529dc9 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -1,6 +1,7 @@ # syntax=docker/dockerfile:1 -FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.17 +# update to alpine 3.18 from archived linuxserver/docker-cops version +FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.18 # set version label ARG BUILD_DATE @@ -11,36 +12,40 @@ LABEL maintainer="chbmb" RUN \ echo "**** install runtime packages ****" && \ + # update to PHP 8.2 from archived linuxserver/docker-cops version apk add --no-cache --upgrade \ - php81-ctype \ - php81-dom \ - php81-gd \ - php81-intl \ - php81-opcache \ - php81-phar \ - php81-pdo_sqlite \ - php81-zip && \ + # libxml2 \ + php82-dom \ + php82-gd \ + php82-intl \ + # php82-json \ + php82-mbstring \ + php82-pdo_sqlite \ + php82-sqlite3 \ + php82-xml \ + php82-xmlwriter \ + php82-zip && \ + echo "**** configure php-fpm to pass env vars ****" && \ + sed -E -i 's/^;?clear_env ?=.*$/clear_env = no/g' /etc/php82/php-fpm.d/www.conf && \ + grep -qxF 'clear_env = no' /etc/php82/php-fpm.d/www.conf || echo 'clear_env = no' >> /etc/php82/php-fpm.d/www.conf && \ + echo "env[PATH] = /usr/local/bin:/usr/bin:/bin" >> /etc/php82/php-fpm.conf && \ echo "**** install cops ****" && \ - curl \ - -sS https://getcomposer.org/installer \ - | php -- --install-dir=/usr/bin --filename=composer --version=1.10.26 && \ - composer \ - global require "fxp/composer-asset-plugin:~1.1" && \ + # use fork mikespub-org/seblucas-cops for PHP 8.x if [ -z ${COPS_RELEASE+x} ]; then \ - COPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/seblucas/cops/releases/latest" \ + COPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/mikespub-org/seblucas-cops/releases/latest" \ | awk '/tag_name/{print $4;exit}' FS='[""]'); \ fi && \ curl -o \ /tmp/cops.tar.gz -L \ - "https://github.com/seblucas/cops/archive/${COPS_RELEASE}.tar.gz" && \ + "https://github.com/mikespub-org/seblucas-cops/archive/${COPS_RELEASE}.tar.gz" && \ mkdir -p \ /app/www/public && \ tar xf /tmp/cops.tar.gz -C \ /app/www/public --strip-components=1 && \ cd /app/www/public && \ + # use standard composer 2.x now, no need to install older 1.x version composer \ install --no-dev --optimize-autoloader && \ - sed -i 's|^[[:space:]]*return[[:space:]]@create_function[[:space:]]'\(''\''\$it'\'',[[:space:]]\$func'\)';| return function \(\$it\) use \(\$func\) \{\n return eval\(\$func\);\n \};|' vendor/seblucas/dot-php/doT.php && \ echo "**** cleanup ****" && \ rm -rf \ /root/.composer \ From 56ee1162add873b1a691b5dd3e730719e014d66c Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:42:51 -0400 Subject: [PATCH 03/19] Delete Dockerfile.armhf --- Dockerfile.armhf | 54 ------------------------------------------------ 1 file changed, 54 deletions(-) delete mode 100644 Dockerfile.armhf diff --git a/Dockerfile.armhf b/Dockerfile.armhf deleted file mode 100644 index fe19387..0000000 --- a/Dockerfile.armhf +++ /dev/null @@ -1,54 +0,0 @@ -# syntax=docker/dockerfile:1 - -FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm32v7-3.17 - -# set version label -ARG BUILD_DATE -ARG VERSION -ARG COPS_RELEASE -LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="chbmb" - -RUN \ - echo "**** install runtime packages ****" && \ - apk add --no-cache --upgrade \ - php81-ctype \ - php81-dom \ - php81-gd \ - php81-intl \ - php81-opcache \ - php81-phar \ - php81-pdo_sqlite \ - php81-zip && \ - echo "**** install cops ****" && \ - curl \ - -sS https://getcomposer.org/installer \ - | php -- --install-dir=/usr/bin --filename=composer --version=1.10.26 && \ - composer \ - global require "fxp/composer-asset-plugin:~1.1" && \ - if [ -z ${COPS_RELEASE+x} ]; then \ - COPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/seblucas/cops/releases/latest" \ - | awk '/tag_name/{print $4;exit}' FS='[""]'); \ - fi && \ - curl -o \ - /tmp/cops.tar.gz -L \ - "https://github.com/seblucas/cops/archive/${COPS_RELEASE}.tar.gz" && \ - mkdir -p \ - /app/www/public && \ - tar xf /tmp/cops.tar.gz -C \ - /app/www/public --strip-components=1 && \ - cd /app/www/public && \ - composer \ - install --no-dev --optimize-autoloader && \ - sed -i 's|^[[:space:]]*return[[:space:]]@create_function[[:space:]]'\(''\''\$it'\'',[[:space:]]\$func'\)';| return function \(\$it\) use \(\$func\) \{\n return eval\(\$func\);\n \};|' vendor/seblucas/dot-php/doT.php && \ - echo "**** cleanup ****" && \ - rm -rf \ - /root/.composer \ - /tmp/* - -# add local files -COPY root/ / - -# ports and volumes -EXPOSE 80 443 -VOLUME /config From a960de74c5964fa928d7ffda4ac4540fe095a79c Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:44:04 -0400 Subject: [PATCH 04/19] Update jenkins-vars.yml --- jenkins-vars.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jenkins-vars.yml b/jenkins-vars.yml index 4969bf3..633b3c2 100644 --- a/jenkins-vars.yml +++ b/jenkins-vars.yml @@ -5,10 +5,10 @@ project_name: docker-cops external_type: github_stable release_type: stable release_tag: latest -ls_branch: master +ls_branch: mikespub repo_vars: - EXT_GIT_BRANCH = 'master' - - EXT_USER = 'seblucas' + - EXT_USER = 'mikespub' - EXT_REPO = 'cops' - BUILD_VERSION_ARG = 'COPS_RELEASE' - LS_USER = 'linuxserver' From 7e9366ab65a78b63cebf6df7068bb49a44376b84 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:47:43 -0400 Subject: [PATCH 05/19] Update readme-vars.yml --- readme-vars.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/readme-vars.yml b/readme-vars.yml index 45a3125..096839a 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -5,7 +5,7 @@ project_name: cops project_url: "http://blog.slucas.fr/en/oss/calibre-opds-php-server" project_logo: "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/cops-icon.png" project_blurb: | - [{{ project_name|capitalize }}]({{ project_url }}) by Sébastien Lucas, stands for Calibre OPDS (and HTML) Php Server. + [{{ project_name|capitalize }}]({{ project_url }}) by Sébastien Lucas, now maintained by MikesPub, stands for Calibre OPDS (and HTML) Php Server. COPS links to your Calibre library database and allows downloading and emailing of books directly from a web browser and provides a OPDS feed to connect to your devices. @@ -39,15 +39,12 @@ project_blurb: | If you want to use the OPDS feed don't forget to specify feed.php at the end of your URL. project_lsio_github_repo_url: "https://github.com/linuxserver/docker-{{ project_name }}" -project_deprecation_status: true -project_deprecation_message: "COPS has been abandoned by its developers and no actively maintained forks exist at this time." project_blurb_optional_extras_enabled: false # supported architectures available_architectures: - { arch: "{{ arch_x86_64 }}", tag: "amd64-latest"} - { arch: "{{ arch_arm64 }}", tag: "arm64v8-latest"} - - { arch: "{{ arch_armhf }}", tag: "arm32v7-latest"} # development version development_versions: false @@ -86,6 +83,7 @@ app_setup_block: | # changelog changelogs: + - { date: "11.08.23:", desc: "undeprecate and add new branch with mikespub fork which is actively maintained." } - { date: "15.05.23:", desc: "Deprecate due to upstream dev abandonment of project." } - { date: "13.04.23:", desc: "Move ssl.conf include to default.conf." } - { date: "19.01.23:", desc: "Rebase to alpine 3.17 with php8.1." } From a09ed3f67b658b9202d1bac6eebb08c942d02f66 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:51:10 -0400 Subject: [PATCH 06/19] Delete 99-deprecation --- root/etc/cont-init.d/99-deprecation | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100755 root/etc/cont-init.d/99-deprecation diff --git a/root/etc/cont-init.d/99-deprecation b/root/etc/cont-init.d/99-deprecation deleted file mode 100755 index e3ef8ce..0000000 --- a/root/etc/cont-init.d/99-deprecation +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/with-contenv bash -# shellcheck shell=bash - -echo ' -╔════════════════════════════════════════════════════╗ -╠════════════════════════════════════════════════════╣ -║ ║ -║ This image is deprecated. ║ -║ We will not offer support for this image ║ -║ and it will not be updated. ║ -║ ║ -╠════════════════════════════════════════════════════╣ -╚════════════════════════════════════════════════════╝ - -COPS has been abandoned by its developers and no actively maintained forks exist at this time. - -══════════════════════════════════════════════════════' From 3c2339c06c8f98a60e835bf458144a74767f1c24 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:53:38 -0400 Subject: [PATCH 07/19] Update README.md --- README.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6bc33bf..8622a48 100644 --- a/README.md +++ b/README.md @@ -27,12 +27,6 @@ Find us at: * [GitHub](https://github.com/linuxserver) - view the source for all of our repositories. * [Open Collective](https://opencollective.com/linuxserver) - please consider helping us by either donating or contributing to our budget -# DEPRECATION NOTICE - -This image is deprecated. We will not offer support for this image and it will not be updated. -COPS has been abandoned by its developers and no actively maintained forks exist at this time. -# [linuxserver/cops](https://github.com/linuxserver/docker-cops) - [![Scarf.io pulls](https://scarf.sh/installs-badge/linuxserver-ci/linuxserver%2Fcops?color=94398d&label-color=555555&logo-color=ffffff&style=for-the-badge&package-type=docker)](https://scarf.sh/gateway/linuxserver-ci/docker/linuxserver%2Fcops) [![GitHub Stars](https://img.shields.io/github/stars/linuxserver/docker-cops.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-cops) [![GitHub Release](https://img.shields.io/github/release/linuxserver/docker-cops.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-cops/releases) @@ -44,7 +38,7 @@ COPS has been abandoned by its developers and no actively maintained forks exist [![Jenkins Build](https://img.shields.io/jenkins/build?labelColor=555555&logoColor=ffffff&style=for-the-badge&jobUrl=https%3A%2F%2Fci.linuxserver.io%2Fjob%2FDocker-Pipeline-Builders%2Fjob%2Fdocker-cops%2Fjob%2Fmaster%2F&logo=jenkins)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-cops/job/master/) [![LSIO CI](https://img.shields.io/badge/dynamic/yaml?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=CI&query=CI&url=https%3A%2F%2Fci-tests.linuxserver.io%2Flinuxserver%2Fcops%2Flatest%2Fci-status.yml)](https://ci-tests.linuxserver.io/linuxserver/cops/latest/index.html) -[Cops](http://blog.slucas.fr/en/oss/calibre-opds-php-server) by Sébastien Lucas, stands for Calibre OPDS (and HTML) Php Server. +[Cops](http://blog.slucas.fr/en/oss/calibre-opds-php-server) by Sébastien Lucas, now maintained by MikesPub, stands for Calibre OPDS (and HTML) Php Server. COPS links to your Calibre library database and allows downloading and emailing of books directly from a web browser and provides a OPDS feed to connect to your devices. @@ -91,7 +85,6 @@ The architectures supported by this image are: | :----: | :----: | ---- | | x86-64 | ✅ | amd64-\ | | arm64 | ✅ | arm64v8-\ | -| armhf | ✅ | arm32v7-\ | ## Application Setup @@ -262,6 +255,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64 ## Versions +* **11.08.23:** - Undeprecate and add new branch with mikespub fork which is actively maintained. * **15.05.23:** - Deprecate due to upstream dev abandonment of project. * **13.04.23:** - Move ssl.conf include to default.conf. * **19.01.23:** - Rebase to alpine 3.17 with php8.1. From c0a509444cd65da73f8494b65fb49e1f5de72b70 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:53:42 -0400 Subject: [PATCH 08/19] Update readme-vars.yml --- readme-vars.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme-vars.yml b/readme-vars.yml index 096839a..10e90b5 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -83,7 +83,7 @@ app_setup_block: | # changelog changelogs: - - { date: "11.08.23:", desc: "undeprecate and add new branch with mikespub fork which is actively maintained." } + - { date: "11.08.23:", desc: "Undeprecate and add new branch with mikespub fork which is actively maintained." } - { date: "15.05.23:", desc: "Deprecate due to upstream dev abandonment of project." } - { date: "13.04.23:", desc: "Move ssl.conf include to default.conf." } - { date: "19.01.23:", desc: "Rebase to alpine 3.17 with php8.1." } From a97bc5bb1956060099c3977231516648aa92880b Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:11:52 -0400 Subject: [PATCH 09/19] Update Dockerfile --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index a529dc9..ac97deb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,3 @@ -# syntax=docker/dockerfile:1 - -# update to alpine 3.18 from archived linuxserver/docker-cops version FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.18 # set version label @@ -12,7 +9,6 @@ LABEL maintainer="chbmb" RUN \ echo "**** install runtime packages ****" && \ - # update to PHP 8.2 from archived linuxserver/docker-cops version apk add --no-cache --upgrade \ # libxml2 \ php82-dom \ From fa9ca104119eaf477b533daf82e86bdef5cfbecf Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:12:09 -0400 Subject: [PATCH 10/19] Update Dockerfile Co-authored-by: Eric Nemchik --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ac97deb..39ca90e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,6 @@ RUN \ php82-dom \ php82-gd \ php82-intl \ - # php82-json \ php82-mbstring \ php82-pdo_sqlite \ php82-sqlite3 \ From a98e75779992505cd9245040f3ea8cfe455e9d63 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:12:16 -0400 Subject: [PATCH 11/19] Update Dockerfile Co-authored-by: Eric Nemchik --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 39ca90e..0adbc58 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,6 @@ RUN \ php82-dom \ php82-gd \ php82-intl \ - php82-mbstring \ php82-pdo_sqlite \ php82-sqlite3 \ php82-xml \ From b35ac8a0b5d935fb28ac61fbe763d70fb630ad0d Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:12:27 -0400 Subject: [PATCH 12/19] Update Dockerfile Co-authored-by: Eric Nemchik --- Dockerfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0adbc58..8a18df6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,10 +15,7 @@ RUN \ php82-gd \ php82-intl \ php82-pdo_sqlite \ - php82-sqlite3 \ - php82-xml \ - php82-xmlwriter \ - php82-zip && \ + php82-sqlite3 && \ echo "**** configure php-fpm to pass env vars ****" && \ sed -E -i 's/^;?clear_env ?=.*$/clear_env = no/g' /etc/php82/php-fpm.d/www.conf && \ grep -qxF 'clear_env = no' /etc/php82/php-fpm.d/www.conf || echo 'clear_env = no' >> /etc/php82/php-fpm.d/www.conf && \ From ac45195989b3d168368a8b6ec4ec3d36001d8365 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:12:43 -0400 Subject: [PATCH 13/19] Update Dockerfile Co-authored-by: Eric Nemchik --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8a18df6..f9856e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,6 @@ RUN \ grep -qxF 'clear_env = no' /etc/php82/php-fpm.d/www.conf || echo 'clear_env = no' >> /etc/php82/php-fpm.d/www.conf && \ echo "env[PATH] = /usr/local/bin:/usr/bin:/bin" >> /etc/php82/php-fpm.conf && \ echo "**** install cops ****" && \ - # use fork mikespub-org/seblucas-cops for PHP 8.x if [ -z ${COPS_RELEASE+x} ]; then \ COPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/mikespub-org/seblucas-cops/releases/latest" \ | awk '/tag_name/{print $4;exit}' FS='[""]'); \ From 80db2a28ba43cf6ea67d093caed4c765056c21ee Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:12:53 -0400 Subject: [PATCH 14/19] Update Dockerfile Co-authored-by: Eric Nemchik --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f9856e1..163876e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,6 @@ RUN \ tar xf /tmp/cops.tar.gz -C \ /app/www/public --strip-components=1 && \ cd /app/www/public && \ - # use standard composer 2.x now, no need to install older 1.x version composer \ install --no-dev --optimize-autoloader && \ echo "**** cleanup ****" && \ From 8039035ece443436c6c48b6004de8b1ab1cf0492 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:14:28 -0400 Subject: [PATCH 15/19] Update Dockerfile.aarch64 --- Dockerfile.aarch64 | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index a529dc9..f9856e1 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -1,6 +1,3 @@ -# syntax=docker/dockerfile:1 - -# update to alpine 3.18 from archived linuxserver/docker-cops version FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.18 # set version label @@ -12,25 +9,18 @@ LABEL maintainer="chbmb" RUN \ echo "**** install runtime packages ****" && \ - # update to PHP 8.2 from archived linuxserver/docker-cops version apk add --no-cache --upgrade \ # libxml2 \ php82-dom \ php82-gd \ php82-intl \ - # php82-json \ - php82-mbstring \ php82-pdo_sqlite \ - php82-sqlite3 \ - php82-xml \ - php82-xmlwriter \ - php82-zip && \ + php82-sqlite3 && \ echo "**** configure php-fpm to pass env vars ****" && \ sed -E -i 's/^;?clear_env ?=.*$/clear_env = no/g' /etc/php82/php-fpm.d/www.conf && \ grep -qxF 'clear_env = no' /etc/php82/php-fpm.d/www.conf || echo 'clear_env = no' >> /etc/php82/php-fpm.d/www.conf && \ echo "env[PATH] = /usr/local/bin:/usr/bin:/bin" >> /etc/php82/php-fpm.conf && \ echo "**** install cops ****" && \ - # use fork mikespub-org/seblucas-cops for PHP 8.x if [ -z ${COPS_RELEASE+x} ]; then \ COPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/mikespub-org/seblucas-cops/releases/latest" \ | awk '/tag_name/{print $4;exit}' FS='[""]'); \ From 280d5719c62107f3dad95b927a24f014e44a1060 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:14:49 -0400 Subject: [PATCH 16/19] Update jenkins-vars.yml Co-authored-by: Eric Nemchik --- jenkins-vars.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jenkins-vars.yml b/jenkins-vars.yml index 633b3c2..23a5174 100644 --- a/jenkins-vars.yml +++ b/jenkins-vars.yml @@ -8,8 +8,8 @@ release_tag: latest ls_branch: mikespub repo_vars: - EXT_GIT_BRANCH = 'master' - - EXT_USER = 'mikespub' - - EXT_REPO = 'cops' + - EXT_USER = 'mikespub-org' + - EXT_REPO = 'seblucas-cops' - BUILD_VERSION_ARG = 'COPS_RELEASE' - LS_USER = 'linuxserver' - LS_REPO = 'docker-cops' From aaef376bac24ece155c1d66b40a4caa1d756599e Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 19:35:59 -0400 Subject: [PATCH 17/19] Update Dockerfile --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 163876e..a8fb9f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.18 # set version label From 452d4872488ba41e5766513e4ab8ef42f1ce9251 Mon Sep 17 00:00:00 2001 From: driz <40674481+drizuid@users.noreply.github.com> Date: Fri, 11 Aug 2023 19:36:17 -0400 Subject: [PATCH 18/19] Update Dockerfile.aarch64 --- Dockerfile.aarch64 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index f9856e1..944afb1 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.18 # set version label From 05ba4cf58f8c46aed64e87bfd94f3789eaf0ee15 Mon Sep 17 00:00:00 2001 From: Eric Nemchik Date: Fri, 11 Aug 2023 19:44:22 -0500 Subject: [PATCH 19/19] Adjust branch in jenkins vars and run builder Signed-off-by: Eric Nemchik --- .github/ISSUE_TEMPLATE/issue.bug.yml | 74 +- .github/ISSUE_TEMPLATE/issue.feature.yml | 31 +- .github/PULL_REQUEST_TEMPLATE.md | 4 - .github/workflows/call_issue_pr_tracker.yml | 16 + .github/workflows/call_issues_cron.yml | 13 + .github/workflows/external_trigger.yml | 104 ++ .../workflows/external_trigger_scheduler.yml | 45 + .github/workflows/package_trigger.yml | 42 + .../workflows/package_trigger_scheduler.yml | 50 + Jenkinsfile | 1007 +++++++++++++++++ README.md | 3 + jenkins-vars.yml | 4 +- 12 files changed, 1374 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/call_issue_pr_tracker.yml create mode 100644 .github/workflows/call_issues_cron.yml create mode 100644 .github/workflows/external_trigger.yml create mode 100644 .github/workflows/external_trigger_scheduler.yml create mode 100644 .github/workflows/package_trigger.yml create mode 100644 .github/workflows/package_trigger_scheduler.yml create mode 100644 Jenkinsfile diff --git a/.github/ISSUE_TEMPLATE/issue.bug.yml b/.github/ISSUE_TEMPLATE/issue.bug.yml index f9d4281..ce3d19a 100755 --- a/.github/ISSUE_TEMPLATE/issue.bug.yml +++ b/.github/ISSUE_TEMPLATE/issue.bug.yml @@ -4,11 +4,73 @@ description: Create a report to help us improve title: "[BUG] " labels: [Bug] body: - - type: markdown + - type: checkboxes attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Current Behavior + description: Tell us what happens instead of the expected behavior. + validations: + required: true + - type: textarea + attributes: + label: Expected Behavior + description: Tell us what should happen. + validations: + required: false + - type: textarea + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. In this environment... + 2. With this config... + 3. Run '...' + 4. See error... + validations: + required: true + - type: textarea + attributes: + label: Environment + description: | + examples: + - **OS**: Ubuntu 20.04 + - **How docker service was installed**: distro's packagemanager value: | - # DEPRECATION NOTICE - - This image is deprecated. We will not offer support for this image and it will not be updated. - - COPS has been abandoned by its developers and no actively maintained forks exist at this time. + - OS: + - How docker service was installed: + render: markdown + validations: + required: false + - type: dropdown + attributes: + label: CPU architecture + options: + - x86-64 + - arm64 + validations: + required: true + - type: textarea + attributes: + label: Docker creation + description: | + Command used to create docker container + Provide your docker create/run command or compose yaml snippet, or a screenshot of settings if using a gui to create the container + render: bash + validations: + required: true + - type: textarea + attributes: + description: | + Provide a full docker log, output of "docker logs linuxserver.io" + label: Container logs + placeholder: | + Output of `docker logs linuxserver.io` + render: bash + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/issue.feature.yml b/.github/ISSUE_TEMPLATE/issue.feature.yml index c2f68fc..099dcdb 100755 --- a/.github/ISSUE_TEMPLATE/issue.feature.yml +++ b/.github/ISSUE_TEMPLATE/issue.feature.yml @@ -4,11 +4,28 @@ description: Suggest an idea for this project title: "[FEAT] <title>" labels: [enhancement] body: - - type: markdown + - type: checkboxes attributes: - value: | - # DEPRECATION NOTICE - - This image is deprecated. We will not offer support for this image and it will not be updated. - - COPS has been abandoned by its developers and no actively maintained forks exist at this time. + label: Is this a new feature request? + description: Please search to see if a feature request already exists. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Wanted change + description: Tell us what you want to happen. + validations: + required: true + - type: textarea + attributes: + label: Reason for change + description: Justify your request, why do you want it, what is the benefit. + validations: + required: true + - type: textarea + attributes: + label: Proposed code change + description: Do you have a potential code change in mind? + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6d27392..eef3a96 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,3 @@ -# DEPRECATION NOTICE - -This image is deprecated. We will not offer support for this image and it will not be updated. -COPS has been abandoned by its developers and no actively maintained forks exist at this time. <!--- Provide a general summary of your changes in the Title above --> [linuxserverurl]: https://linuxserver.io diff --git a/.github/workflows/call_issue_pr_tracker.yml b/.github/workflows/call_issue_pr_tracker.yml new file mode 100644 index 0000000..2c30784 --- /dev/null +++ b/.github/workflows/call_issue_pr_tracker.yml @@ -0,0 +1,16 @@ +name: Issue & PR Tracker + +on: + issues: + types: [opened,reopened,labeled,unlabeled,closed] + pull_request_target: + types: [opened,reopened,review_requested,review_request_removed,labeled,unlabeled,closed] + pull_request_review: + types: [submitted,edited,dismissed] + +jobs: + manage-project: + permissions: + issues: write + uses: linuxserver/github-workflows/.github/workflows/issue-pr-tracker.yml@v1 + secrets: inherit diff --git a/.github/workflows/call_issues_cron.yml b/.github/workflows/call_issues_cron.yml new file mode 100644 index 0000000..559a6c8 --- /dev/null +++ b/.github/workflows/call_issues_cron.yml @@ -0,0 +1,13 @@ +name: Mark stale issues and pull requests +on: + schedule: + - cron: '40 3 * * *' + workflow_dispatch: + +jobs: + stale: + permissions: + issues: write + pull-requests: write + uses: linuxserver/github-workflows/.github/workflows/issues-cron.yml@v1 + secrets: inherit diff --git a/.github/workflows/external_trigger.yml b/.github/workflows/external_trigger.yml new file mode 100644 index 0000000..ae6f06d --- /dev/null +++ b/.github/workflows/external_trigger.yml @@ -0,0 +1,104 @@ +name: External Trigger Main + +on: + workflow_dispatch: + +jobs: + external-trigger-master: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.1.0 + + - name: External Trigger + if: github.ref == 'refs/heads/master' + run: | + if [ -n "${{ secrets.PAUSE_EXTERNAL_TRIGGER_COPS_MASTER }}" ]; then + echo "**** Github secret PAUSE_EXTERNAL_TRIGGER_COPS_MASTER is set; skipping trigger. ****" + echo "Github secret \`PAUSE_EXTERNAL_TRIGGER_COPS_MASTER\` is set; skipping trigger." >> $GITHUB_STEP_SUMMARY + exit 0 + fi + echo "**** External trigger running off of master branch. To disable this trigger, set a Github secret named \"PAUSE_EXTERNAL_TRIGGER_COPS_MASTER\". ****" + echo "External trigger running off of master branch. To disable this trigger, set a Github secret named \`PAUSE_EXTERNAL_TRIGGER_COPS_MASTER\`" >> $GITHUB_STEP_SUMMARY + echo "**** Retrieving external version ****" + EXT_RELEASE=$(curl -u "${{ secrets.CR_USER }}:${{ secrets.CR_PAT }}" -sX GET "https://api.github.com/repos/mikespub-org/seblucas-cops/releases/latest" | jq -r '. | .tag_name') + if [ -z "${EXT_RELEASE}" ] || [ "${EXT_RELEASE}" == "null" ]; then + echo "**** Can't retrieve external version, exiting ****" + FAILURE_REASON="Can't retrieve external version for cops branch master" + GHA_TRIGGER_URL="https://github.com/linuxserver/docker-cops/actions/runs/${{ github.run_id }}" + curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 16711680, + "description": "**Trigger Failed** \n**Reason:** '"${FAILURE_REASON}"' \n**Trigger URL:** '"${GHA_TRIGGER_URL}"' \n"}], + "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} + exit 1 + fi + EXT_RELEASE=$(echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g') + echo "**** External version: ${EXT_RELEASE} ****" + echo "External version: ${EXT_RELEASE}" >> $GITHUB_STEP_SUMMARY + echo "**** Retrieving last pushed version ****" + image="linuxserver/cops" + tag="latest" + token=$(curl -sX GET \ + "https://ghcr.io/token?scope=repository%3Alinuxserver%2Fcops%3Apull" \ + | jq -r '.token') + multidigest=$(curl -s \ + --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ + --header "Authorization: Bearer ${token}" \ + "https://ghcr.io/v2/${image}/manifests/${tag}" \ + | jq -r 'first(.manifests[].digest)') + digest=$(curl -s \ + --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ + --header "Authorization: Bearer ${token}" \ + "https://ghcr.io/v2/${image}/manifests/${multidigest}" \ + | jq -r '.config.digest') + image_info=$(curl -sL \ + --header "Authorization: Bearer ${token}" \ + "https://ghcr.io/v2/${image}/blobs/${digest}") + if [[ $(echo $image_info | jq -r '.container_config') == "null" ]]; then + image_info=$(echo $image_info | jq -r '.config') + else + image_info=$(echo $image_info | jq -r '.container_config') + fi + IMAGE_RELEASE=$(echo ${image_info} | jq -r '.Labels.build_version' | awk '{print $3}') + IMAGE_VERSION=$(echo ${IMAGE_RELEASE} | awk -F'-ls' '{print $1}') + if [ -z "${IMAGE_VERSION}" ]; then + echo "**** Can't retrieve last pushed version, exiting ****" + FAILURE_REASON="Can't retrieve last pushed version for cops tag latest" + curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 16711680, + "description": "**Trigger Failed** \n**Reason:** '"${FAILURE_REASON}"' \n"}], + "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} + exit 1 + fi + echo "**** Last pushed version: ${IMAGE_VERSION} ****" + echo "Last pushed version: ${IMAGE_VERSION}" >> $GITHUB_STEP_SUMMARY + if [ "${EXT_RELEASE}" == "${IMAGE_VERSION}" ]; then + echo "**** Version ${EXT_RELEASE} already pushed, exiting ****" + echo "Version ${EXT_RELEASE} already pushed, exiting" >> $GITHUB_STEP_SUMMARY + exit 0 + elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-cops/job/master/lastBuild/api/json | jq -r '.building') == "true" ]; then + echo "**** New version ${EXT_RELEASE} found; but there already seems to be an active build on Jenkins; exiting ****" + echo "New version ${EXT_RELEASE} found; but there already seems to be an active build on Jenkins; exiting" >> $GITHUB_STEP_SUMMARY + exit 0 + else + echo "**** New version ${EXT_RELEASE} found; old version was ${IMAGE_VERSION}. Triggering new build ****" + echo "New version ${EXT_RELEASE} found; old version was ${IMAGE_VERSION}. Triggering new build" >> $GITHUB_STEP_SUMMARY + response=$(curl -iX POST \ + https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-cops/job/master/buildWithParameters?PACKAGE_CHECK=false \ + --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") + echo "**** Jenkins job queue url: ${response%$'\r'} ****" + echo "**** Sleeping 10 seconds until job starts ****" + sleep 10 + buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url') + buildurl="${buildurl%$'\r'}" + echo "**** Jenkins job build url: ${buildurl} ****" + echo "Jenkins job build url: ${buildurl}" >> $GITHUB_STEP_SUMMARY + echo "**** Attempting to change the Jenkins job description ****" + curl -iX POST \ + "${buildurl}submitDescription" \ + --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \ + --data-urlencode "description=GHA external trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --data-urlencode "Submit=Submit" + echo "**** Notifying Discord ****" + TRIGGER_REASON="A version change was detected for cops tag latest. Old version:${IMAGE_VERSION} New version:${EXT_RELEASE}" + curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903, + "description": "**Build Triggered** \n**Reason:** '"${TRIGGER_REASON}"' \n**Build URL:** '"${buildurl}display/redirect"' \n"}], + "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} + fi diff --git a/.github/workflows/external_trigger_scheduler.yml b/.github/workflows/external_trigger_scheduler.yml new file mode 100644 index 0000000..ed84bda --- /dev/null +++ b/.github/workflows/external_trigger_scheduler.yml @@ -0,0 +1,45 @@ +name: External Trigger Scheduler + +on: + schedule: + - cron: '37 * * * *' + workflow_dispatch: + +jobs: + external-trigger-scheduler: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.1.0 + with: + fetch-depth: '0' + + - name: External Trigger Scheduler + run: | + echo "**** Branches found: ****" + git for-each-ref --format='%(refname:short)' refs/remotes + for br in $(git for-each-ref --format='%(refname:short)' refs/remotes) + do + br=$(echo "$br" | sed 's|origin/||g') + echo "**** Evaluating branch ${br} ****" + ls_jenkins_vars=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-cops/${br}/jenkins-vars.yml) + ls_branch=$(echo "${ls_jenkins_vars}" | yq -r '.ls_branch') + ls_trigger=$(echo "${ls_jenkins_vars}" | yq -r '.external_type') + if [[ "${br}" == "${ls_branch}" ]] && [[ "${ls_trigger}" != "os" ]]; then + echo "**** Branch ${br} appears to be live and trigger is not os; checking workflow. ****" + if curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-cops/${br}/.github/workflows/external_trigger.yml > /dev/null 2>&1; then + echo "**** Workflow exists. Triggering external trigger workflow for branch ${br} ****." + echo "Triggering external trigger workflow for branch ${br}" >> $GITHUB_STEP_SUMMARY + curl -iX POST \ + -H "Authorization: token ${{ secrets.CR_PAT }}" \ + -H "Accept: application/vnd.github.v3+json" \ + -d "{\"ref\":\"refs/heads/${br}\"}" \ + https://api.github.com/repos/linuxserver/docker-cops/actions/workflows/external_trigger.yml/dispatches + else + echo "**** Workflow doesn't exist; skipping trigger. ****" + echo "Skipping branch ${br} due to no external trigger workflow present." >> $GITHUB_STEP_SUMMARY + fi + else + echo "**** ${br} is either a dev branch, or has no external version; skipping trigger. ****" + echo "Skipping branch ${br} due to being detected as dev branch or having no external version." >> $GITHUB_STEP_SUMMARY + fi + done diff --git a/.github/workflows/package_trigger.yml b/.github/workflows/package_trigger.yml new file mode 100644 index 0000000..511d2f1 --- /dev/null +++ b/.github/workflows/package_trigger.yml @@ -0,0 +1,42 @@ +name: Package Trigger Main + +on: + workflow_dispatch: + +jobs: + package-trigger-master: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.1.0 + + - name: Package Trigger + if: github.ref == 'refs/heads/master' + run: | + if [ -n "${{ secrets.PAUSE_PACKAGE_TRIGGER_COPS_MASTER }}" ]; then + echo "**** Github secret PAUSE_PACKAGE_TRIGGER_COPS_MASTER is set; skipping trigger. ****" + echo "Github secret \`PAUSE_PACKAGE_TRIGGER_COPS_MASTER\` is set; skipping trigger." >> $GITHUB_STEP_SUMMARY + exit 0 + fi + if [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-cops/job/master/lastBuild/api/json | jq -r '.building') == "true" ]; then + echo "**** There already seems to be an active build on Jenkins; skipping package trigger ****" + echo "There already seems to be an active build on Jenkins; skipping package trigger" >> $GITHUB_STEP_SUMMARY + exit 0 + fi + echo "**** Package trigger running off of master branch. To disable, set a Github secret named \"PAUSE_PACKAGE_TRIGGER_COPS_MASTER\". ****" + echo "Package trigger running off of master branch. To disable, set a Github secret named \`PAUSE_PACKAGE_TRIGGER_COPS_MASTER\`" >> $GITHUB_STEP_SUMMARY + response=$(curl -iX POST \ + https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-cops/job/master/buildWithParameters?PACKAGE_CHECK=true \ + --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") + echo "**** Jenkins job queue url: ${response%$'\r'} ****" + echo "**** Sleeping 10 seconds until job starts ****" + sleep 10 + buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url') + buildurl="${buildurl%$'\r'}" + echo "**** Jenkins job build url: ${buildurl} ****" + echo "Jenkins job build url: ${buildurl}" >> $GITHUB_STEP_SUMMARY + echo "**** Attempting to change the Jenkins job description ****" + curl -iX POST \ + "${buildurl}submitDescription" \ + --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \ + --data-urlencode "description=GHA package trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --data-urlencode "Submit=Submit" diff --git a/.github/workflows/package_trigger_scheduler.yml b/.github/workflows/package_trigger_scheduler.yml new file mode 100644 index 0000000..e7d5c2d --- /dev/null +++ b/.github/workflows/package_trigger_scheduler.yml @@ -0,0 +1,50 @@ +name: Package Trigger Scheduler + +on: + schedule: + - cron: '49 20 * * 0' + workflow_dispatch: + +jobs: + package-trigger-scheduler: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.1.0 + with: + fetch-depth: '0' + + - name: Package Trigger Scheduler + run: | + echo "**** Branches found: ****" + git for-each-ref --format='%(refname:short)' refs/remotes + for br in $(git for-each-ref --format='%(refname:short)' refs/remotes) + do + br=$(echo "$br" | sed 's|origin/||g') + echo "**** Evaluating branch ${br} ****" + ls_branch=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-cops/${br}/jenkins-vars.yml | yq -r '.ls_branch') + if [ "${br}" == "${ls_branch}" ]; then + echo "**** Branch ${br} appears to be live; checking workflow. ****" + if curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-cops/${br}/.github/workflows/package_trigger.yml > /dev/null 2>&1; then + echo "**** Workflow exists. Triggering package trigger workflow for branch ${br}. ****" + echo "Triggering package trigger workflow for branch ${br}" >> $GITHUB_STEP_SUMMARY + triggered_branches="${triggered_branches}${br} " + curl -iX POST \ + -H "Authorization: token ${{ secrets.CR_PAT }}" \ + -H "Accept: application/vnd.github.v3+json" \ + -d "{\"ref\":\"refs/heads/${br}\"}" \ + https://api.github.com/repos/linuxserver/docker-cops/actions/workflows/package_trigger.yml/dispatches + sleep 30 + else + echo "**** Workflow doesn't exist; skipping trigger. ****" + echo "Skipping branch ${br} due to no package trigger workflow present." >> $GITHUB_STEP_SUMMARY + fi + else + echo "**** ${br} appears to be a dev branch; skipping trigger. ****" + echo "Skipping branch ${br} due to being detected as dev branch." >> $GITHUB_STEP_SUMMARY + fi + done + echo "**** Package check build(s) triggered for branch(es): ${triggered_branches} ****" + echo "**** Notifying Discord ****" + curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903, + "description": "**Package Check Build(s) Triggered for cops** \n**Branch(es):** '"${triggered_branches}"' \n**Build URL:** '"https://ci.linuxserver.io/blue/organizations/jenkins/Docker-Pipeline-Builders%2Fdocker-cops/activity/"' \n"}], + "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..95cb43e --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,1007 @@ +pipeline { + agent { + label 'X86-64-MULTI' + } + options { + buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '60')) + parallelsAlwaysFailFast() + } + // Input to determine if this is a package check + parameters { + string(defaultValue: 'false', description: 'package check run', name: 'PACKAGE_CHECK') + } + // Configuration for the variables used for this specific repo + environment { + BUILDS_DISCORD=credentials('build_webhook_url') + GITHUB_TOKEN=credentials('498b4638-2d02-4ce5-832d-8a57d01d97ab') + GITLAB_TOKEN=credentials('b6f0f1dd-6952-4cf6-95d1-9c06380283f0') + GITLAB_NAMESPACE=credentials('gitlab-namespace-id') + SCARF_TOKEN=credentials('scarf_api_key') + EXT_GIT_BRANCH = 'main' + EXT_USER = 'mikespub-org' + EXT_REPO = 'seblucas-cops' + BUILD_VERSION_ARG = 'COPS_RELEASE' + LS_USER = 'linuxserver' + LS_REPO = 'docker-cops' + CONTAINER_NAME = 'cops' + DOCKERHUB_IMAGE = 'linuxserver/cops' + DEV_DOCKERHUB_IMAGE = 'lsiodev/cops' + PR_DOCKERHUB_IMAGE = 'lspipepr/cops' + DIST_IMAGE = 'alpine' + MULTIARCH='true' + CI='true' + CI_WEB='true' + CI_PORT='80' + CI_SSL='false' + CI_DELAY='120' + CI_DOCKERENV='TZ=US/Pacific' + CI_AUTH='user:password' + CI_WEBPATH='' + } + stages { + // Setup all the basic environment variables needed for the build + stage("Set ENV Variables base"){ + steps{ + sh '''#! /bin/bash + containers=$(docker ps -aq) + if [[ -n "${containers}" ]]; then + docker stop ${containers} + fi + docker system prune -af --volumes || : ''' + script{ + env.EXIT_STATUS = '' + env.LS_RELEASE = sh( + script: '''docker run --rm quay.io/skopeo/stable:v1 inspect docker://ghcr.io/${LS_USER}/${CONTAINER_NAME}:latest 2>/dev/null | jq -r '.Labels.build_version' | awk '{print $3}' | grep '\\-ls' || : ''', + returnStdout: true).trim() + env.LS_RELEASE_NOTES = sh( + script: '''cat readme-vars.yml | awk -F \\" '/date: "[0-9][0-9].[0-9][0-9].[0-9][0-9]:/ {print $4;exit;}' | sed -E ':a;N;$!ba;s/\\r{0,1}\\n/\\\\n/g' ''', + returnStdout: true).trim() + env.GITHUB_DATE = sh( + script: '''date '+%Y-%m-%dT%H:%M:%S%:z' ''', + returnStdout: true).trim() + env.COMMIT_SHA = sh( + script: '''git rev-parse HEAD''', + returnStdout: true).trim() + env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/commit/' + env.GIT_COMMIT + env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DOCKERHUB_IMAGE + '/tags/' + env.PULL_REQUEST = env.CHANGE_ID + env.TEMPLATED_FILES = 'Jenkinsfile README.md LICENSE .editorconfig ./.github/CONTRIBUTING.md ./.github/FUNDING.yml ./.github/ISSUE_TEMPLATE/config.yml ./.github/ISSUE_TEMPLATE/issue.bug.yml ./.github/ISSUE_TEMPLATE/issue.feature.yml ./.github/PULL_REQUEST_TEMPLATE.md ./.github/workflows/external_trigger_scheduler.yml ./.github/workflows/greetings.yml ./.github/workflows/package_trigger_scheduler.yml ./.github/workflows/call_issue_pr_tracker.yml ./.github/workflows/call_issues_cron.yml ./.github/workflows/permissions.yml ./.github/workflows/external_trigger.yml ./.github/workflows/package_trigger.yml' + } + script{ + env.LS_RELEASE_NUMBER = sh( + script: '''echo ${LS_RELEASE} |sed 's/^.*-ls//g' ''', + returnStdout: true).trim() + } + script{ + env.LS_TAG_NUMBER = sh( + script: '''#! /bin/bash + tagsha=$(git rev-list -n 1 ${LS_RELEASE} 2>/dev/null) + if [ "${tagsha}" == "${COMMIT_SHA}" ]; then + echo ${LS_RELEASE_NUMBER} + elif [ -z "${GIT_COMMIT}" ]; then + echo ${LS_RELEASE_NUMBER} + else + echo $((${LS_RELEASE_NUMBER} + 1)) + fi''', + returnStdout: true).trim() + } + } + } + /* ####################### + Package Version Tagging + ####################### */ + // Grab the current package versions in Git to determine package tag + stage("Set Package tag"){ + steps{ + script{ + env.PACKAGE_TAG = sh( + script: '''#!/bin/bash + if [ -e package_versions.txt ] ; then + cat package_versions.txt | md5sum | cut -c1-8 + else + echo none + fi''', + returnStdout: true).trim() + } + } + } + /* ######################## + External Release Tagging + ######################## */ + // If this is a stable github release use the latest endpoint from github to determine the ext tag + stage("Set ENV github_stable"){ + steps{ + script{ + env.EXT_RELEASE = sh( + script: '''curl -H "Authorization: token ${GITHUB_TOKEN}" -s https://api.github.com/repos/${EXT_USER}/${EXT_REPO}/releases/latest | jq -r '. | .tag_name' ''', + returnStdout: true).trim() + } + } + } + // If this is a stable or devel github release generate the link for the build message + stage("Set ENV github_link"){ + steps{ + script{ + env.RELEASE_LINK = 'https://github.com/' + env.EXT_USER + '/' + env.EXT_REPO + '/releases/tag/' + env.EXT_RELEASE + } + } + } + // Sanitize the release tag and strip illegal docker or github characters + stage("Sanitize tag"){ + steps{ + script{ + env.EXT_RELEASE_CLEAN = sh( + script: '''echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g' ''', + returnStdout: true).trim() + + def semver = env.EXT_RELEASE_CLEAN =~ /(\d+)\.(\d+)\.(\d+)/ + if (semver.find()) { + env.SEMVER = "${semver[0][1]}.${semver[0][2]}.${semver[0][3]}" + } else { + semver = env.EXT_RELEASE_CLEAN =~ /(\d+)\.(\d+)(?:\.(\d+))?(.*)/ + if (semver.find()) { + if (semver[0][3]) { + env.SEMVER = "${semver[0][1]}.${semver[0][2]}.${semver[0][3]}" + } else if (!semver[0][3] && !semver[0][4]) { + env.SEMVER = "${semver[0][1]}.${semver[0][2]}.${(new Date()).format('YYYYMMdd')}" + } + } + } + + if (env.SEMVER != null) { + if (BRANCH_NAME != "master" && BRANCH_NAME != "main") { + env.SEMVER = "${env.SEMVER}-${BRANCH_NAME}" + } + println("SEMVER: ${env.SEMVER}") + } else { + println("No SEMVER detected") + } + + } + } + } + // If this is a master build use live docker endpoints + stage("Set ENV live build"){ + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + } + steps { + script{ + env.IMAGE = env.DOCKERHUB_IMAGE + env.GITHUBIMAGE = 'ghcr.io/' + env.LS_USER + '/' + env.CONTAINER_NAME + env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/' + env.CONTAINER_NAME + env.QUAYIMAGE = 'quay.io/linuxserver.io/' + env.CONTAINER_NAME + if (env.MULTIARCH == 'true') { + env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + } else { + env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + } + env.VERSION_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + env.META_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN + } + } + } + // If this is a dev build use dev docker endpoints + stage("Set ENV dev build"){ + when { + not {branch "master"} + environment name: 'CHANGE_ID', value: '' + } + steps { + script{ + env.IMAGE = env.DEV_DOCKERHUB_IMAGE + env.GITHUBIMAGE = 'ghcr.io/' + env.LS_USER + '/lsiodev-' + env.CONTAINER_NAME + env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/lsiodev-' + env.CONTAINER_NAME + env.QUAYIMAGE = 'quay.io/linuxserver.io/lsiodev-' + env.CONTAINER_NAME + if (env.MULTIARCH == 'true') { + env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + } else { + env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + } + env.VERSION_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + env.META_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN + env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DEV_DOCKERHUB_IMAGE + '/tags/' + } + } + } + // If this is a pull request build use dev docker endpoints + stage("Set ENV PR build"){ + when { + not {environment name: 'CHANGE_ID', value: ''} + } + steps { + script{ + env.IMAGE = env.PR_DOCKERHUB_IMAGE + env.GITHUBIMAGE = 'ghcr.io/' + env.LS_USER + '/lspipepr-' + env.CONTAINER_NAME + env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/lspipepr-' + env.CONTAINER_NAME + env.QUAYIMAGE = 'quay.io/linuxserver.io/lspipepr-' + env.CONTAINER_NAME + if (env.MULTIARCH == 'true') { + env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST + } else { + env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST + } + env.VERSION_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST + env.META_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST + env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN + 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/' + } + } + } + // Run ShellCheck + stage('ShellCheck') { + when { + environment name: 'CI', value: 'true' + } + steps { + withCredentials([ + string(credentialsId: 'ci-tests-s3-key-id', variable: 'S3_KEY'), + string(credentialsId: 'ci-tests-s3-secret-access-key', variable: 'S3_SECRET') + ]) { + script{ + env.SHELLCHECK_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/shellcheck-result.xml' + } + sh '''curl -sL https://raw.githubusercontent.com/linuxserver/docker-jenkins-builder/master/checkrun.sh | /bin/bash''' + sh '''#! /bin/bash + docker run --rm \ + -v ${WORKSPACE}:/mnt \ + -e AWS_ACCESS_KEY_ID=\"${S3_KEY}\" \ + -e AWS_SECRET_ACCESS_KEY=\"${S3_SECRET}\" \ + ghcr.io/linuxserver/baseimage-alpine:3.17 s6-envdir -fn -- /var/run/s6/container_environment /bin/bash -c "\ + apk add --no-cache py3-pip && \ + pip install s3cmd && \ + s3cmd put --no-preserve --acl-public -m text/xml /mnt/shellcheck-result.xml s3://ci-tests.linuxserver.io/${IMAGE}/${META_TAG}/shellcheck-result.xml" || :''' + } + } + } + // Use helper containers to render templated files + stage('Update-Templates') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + expression { + env.CONTAINER_NAME != null + } + } + steps { + sh '''#! /bin/bash + set -e + TEMPDIR=$(mktemp -d) + docker pull ghcr.io/linuxserver/jenkins-builder:latest + docker run --rm -e CONTAINER_NAME=${CONTAINER_NAME} -e GITHUB_BRANCH=master -v ${TEMPDIR}:/ansible/jenkins ghcr.io/linuxserver/jenkins-builder:latest + # Stage 1 - Jenkinsfile update + if [[ "$(md5sum Jenkinsfile | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/Jenkinsfile | awk '{ print $1 }')" ]]; then + mkdir -p ${TEMPDIR}/repo + git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/repo/${LS_REPO} + cd ${TEMPDIR}/repo/${LS_REPO} + git checkout -f master + cp ${TEMPDIR}/docker-${CONTAINER_NAME}/Jenkinsfile ${TEMPDIR}/repo/${LS_REPO}/ + git add Jenkinsfile + git commit -m 'Bot Updating Templated Files' + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + echo "Updating Jenkinsfile" + rm -Rf ${TEMPDIR} + exit 0 + else + echo "Jenkinsfile is up to date." + fi + # Stage 2 - Delete old templates + OLD_TEMPLATES=".github/ISSUE_TEMPLATE.md .github/ISSUE_TEMPLATE/issue.bug.md .github/ISSUE_TEMPLATE/issue.feature.md .github/workflows/call_invalid_helper.yml .github/workflows/stale.yml Dockerfile.armhf" + for i in ${OLD_TEMPLATES}; do + if [[ -f "${i}" ]]; then + TEMPLATES_TO_DELETE="${i} ${TEMPLATES_TO_DELETE}" + fi + done + if [[ -n "${TEMPLATES_TO_DELETE}" ]]; then + mkdir -p ${TEMPDIR}/repo + git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/repo/${LS_REPO} + cd ${TEMPDIR}/repo/${LS_REPO} + git checkout -f master + for i in ${TEMPLATES_TO_DELETE}; do + git rm "${i}" + done + git commit -m 'Bot Updating Templated Files' + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + echo "Deleting old and deprecated templates" + rm -Rf ${TEMPDIR} + exit 0 + else + echo "No templates to delete" + fi + # Stage 3 - Update templates + CURRENTHASH=$(grep -hs ^ ${TEMPLATED_FILES} | md5sum | cut -c1-8) + cd ${TEMPDIR}/docker-${CONTAINER_NAME} + NEWHASH=$(grep -hs ^ ${TEMPLATED_FILES} | md5sum | cut -c1-8) + if [[ "${CURRENTHASH}" != "${NEWHASH}" ]] || ! grep -q '.jenkins-external' "${WORKSPACE}/.gitignore" 2>/dev/null; then + mkdir -p ${TEMPDIR}/repo + git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/repo/${LS_REPO} + cd ${TEMPDIR}/repo/${LS_REPO} + git checkout -f master + cd ${TEMPDIR}/docker-${CONTAINER_NAME} + mkdir -p ${TEMPDIR}/repo/${LS_REPO}/.github/workflows + mkdir -p ${TEMPDIR}/repo/${LS_REPO}/.github/ISSUE_TEMPLATE + cp --parents ${TEMPLATED_FILES} ${TEMPDIR}/repo/${LS_REPO}/ || : + cp --parents readme-vars.yml ${TEMPDIR}/repo/${LS_REPO}/ || : + cd ${TEMPDIR}/repo/${LS_REPO}/ + if ! grep -q '.jenkins-external' .gitignore 2>/dev/null; then + echo ".jenkins-external" >> .gitignore + git add .gitignore + fi + git add readme-vars.yml ${TEMPLATED_FILES} + git commit -m 'Bot Updating Templated Files' + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + else + echo "false" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + fi + mkdir -p ${TEMPDIR}/gitbook + git clone https://github.com/linuxserver/docker-documentation.git ${TEMPDIR}/gitbook/docker-documentation + if [[ ("${BRANCH_NAME}" == "master") || ("${BRANCH_NAME}" == "main") ]] && [[ (! -f ${TEMPDIR}/gitbook/docker-documentation/images/docker-${CONTAINER_NAME}.md) || ("$(md5sum ${TEMPDIR}/gitbook/docker-documentation/images/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')") ]]; then + cp ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/docker-${CONTAINER_NAME}.md ${TEMPDIR}/gitbook/docker-documentation/images/ + cd ${TEMPDIR}/gitbook/docker-documentation/ + git add images/docker-${CONTAINER_NAME}.md + git commit -m 'Bot Updating Documentation' + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/docker-documentation.git --all + fi + mkdir -p ${TEMPDIR}/unraid + git clone https://github.com/linuxserver/docker-templates.git ${TEMPDIR}/unraid/docker-templates + git clone https://github.com/linuxserver/templates.git ${TEMPDIR}/unraid/templates + if [[ -f ${TEMPDIR}/unraid/docker-templates/linuxserver.io/img/${CONTAINER_NAME}-logo.png ]]; then + sed -i "s|master/linuxserver.io/img/linuxserver-ls-logo.png|master/linuxserver.io/img/${CONTAINER_NAME}-logo.png|" ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml + elif [[ -f ${TEMPDIR}/unraid/docker-templates/linuxserver.io/img/${CONTAINER_NAME}-icon.png ]]; then + sed -i "s|master/linuxserver.io/img/linuxserver-ls-logo.png|master/linuxserver.io/img/${CONTAINER_NAME}-icon.png|" ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml + fi + if [[ ("${BRANCH_NAME}" == "master") || ("${BRANCH_NAME}" == "main") ]] && [[ (! -f ${TEMPDIR}/unraid/templates/unraid/${CONTAINER_NAME}.xml) || ("$(md5sum ${TEMPDIR}/unraid/templates/unraid/${CONTAINER_NAME}.xml | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml | awk '{ print $1 }')") ]]; then + cd ${TEMPDIR}/unraid/templates/ + if grep -wq "${CONTAINER_NAME}" ${TEMPDIR}/unraid/templates/unraid/ignore.list; then + echo "Image is on the ignore list, marking Unraid template as deprecated" + cp ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml ${TEMPDIR}/unraid/templates/unraid/ + git add -u unraid/${CONTAINER_NAME}.xml + git mv unraid/${CONTAINER_NAME}.xml unraid/deprecated/${CONTAINER_NAME}.xml || : + git commit -m 'Bot Moving Deprecated Unraid Template' || : + else + cp ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml ${TEMPDIR}/unraid/templates/unraid/ + git add unraid/${CONTAINER_NAME}.xml + git commit -m 'Bot Updating Unraid Template' + fi + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/templates.git --all + fi + rm -Rf ${TEMPDIR}''' + script{ + env.FILES_UPDATED = sh( + script: '''cat /tmp/${COMMIT_SHA}-${BUILD_NUMBER}''', + returnStdout: true).trim() + } + } + } + // Exit the build if the Templated files were just updated + stage('Template-exit') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'FILES_UPDATED', value: 'true' + expression { + env.CONTAINER_NAME != null + } + } + steps { + script{ + env.EXIT_STATUS = 'ABORTED' + } + } + } + // If this is a master build check the S6 service file perms + stage("Check S6 Service file Permissions"){ + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'EXIT_STATUS', value: '' + } + steps { + script{ + sh '''#! /bin/bash + WRONG_PERM=$(find ./ -path "./.git" -prune -o \\( -name "run" -o -name "finish" -o -name "check" \\) -not -perm -u=x,g=x,o=x -print) + if [[ -n "${WRONG_PERM}" ]]; then + echo "The following S6 service files are missing the executable bit; canceling the faulty build: ${WRONG_PERM}" + exit 1 + else + echo "S6 service file perms look good." + fi ''' + } + } + } + /* ####################### + GitLab Mirroring + ####################### */ + // Ping into Gitlab to mirror this repo and have a registry endpoint + stage("GitLab Mirror"){ + when { + environment name: 'EXIT_STATUS', value: '' + } + steps{ + sh '''curl -H "Content-Type: application/json" -H "Private-Token: ${GITLAB_TOKEN}" -X POST https://gitlab.com/api/v4/projects \ + -d '{"namespace_id":'${GITLAB_NAMESPACE}',\ + "name":"'${LS_REPO}'", + "mirror":true,\ + "import_url":"https://github.com/linuxserver/'${LS_REPO}'.git",\ + "issues_access_level":"disabled",\ + "merge_requests_access_level":"disabled",\ + "repository_access_level":"enabled",\ + "visibility":"public"}' ''' + } + } + /* ####################### + Scarf.sh package registry + ####################### */ + // Add package to Scarf.sh and set permissions + stage("Scarf.sh package registry"){ + when { + branch "master" + environment name: 'EXIT_STATUS', value: '' + } + steps{ + sh '''#! /bin/bash + PACKAGE_UUID=$(curl -X GET -H "Authorization: Bearer ${SCARF_TOKEN}" https://scarf.sh/api/v1/organizations/linuxserver-ci/packages | jq -r '.[] | select(.name=="linuxserver/cops") | .uuid' || :) + if [ -z "${PACKAGE_UUID}" ]; then + echo "Adding package to Scarf.sh" + curl -sX POST https://scarf.sh/api/v1/organizations/linuxserver-ci/packages \ + -H "Authorization: Bearer ${SCARF_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{"name":"linuxserver/cops",\ + "shortDescription":"example description",\ + "libraryType":"docker",\ + "website":"https://github.com/linuxserver/docker-cops",\ + "backendUrl":"https://ghcr.io/linuxserver/cops",\ + "publicUrl":"https://lscr.io/linuxserver/cops"}' || : + else + echo "Package already exists on Scarf.sh" + fi + ''' + } + } + /* ############### + Build Container + ############### */ + // Build Docker container for push to LS Repo + stage('Build-Single') { + when { + expression { + env.MULTIARCH == 'false' || params.PACKAGE_CHECK == 'true' + } + environment name: 'EXIT_STATUS', value: '' + } + steps { + echo "Running on node: ${NODE_NAME}" + sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile" + sh "docker buildx build \ + --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ + --label \"org.opencontainers.image.authors=linuxserver.io\" \ + --label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-cops/packages\" \ + --label \"org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-cops\" \ + --label \"org.opencontainers.image.source=https://github.com/linuxserver/docker-cops\" \ + --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ + --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ + --label \"org.opencontainers.image.vendor=linuxserver.io\" \ + --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ + --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ + --label \"org.opencontainers.image.title=Cops\" \ + --label \"org.opencontainers.image.description=[Cops](http://blog.slucas.fr/en/oss/calibre-opds-php-server) by Sébastien Lucas, now maintained by MikesPub, stands for Calibre OPDS (and HTML) Php Server. COPS links to your Calibre library database and allows downloading and emailing of books directly from a web browser and provides a OPDS feed to connect to your devices. Changes in your Calibre library are reflected immediately in your COPS pages. See : [COPS's home](http://blog.slucas.fr/en/oss/calibre-opds-php-server) for more details. Don't forget to check the [Wiki](https://github.com/seblucas/cops/wiki). ## Why? (taken from the author's site) In my opinion Calibre is a marvelous tool but is too big and has too much dependencies to be used for its content server. That's the main reason why I coded this OPDS server. I needed a simple tool to be installed on a small server (Seagate Dockstar in my case). I initially thought of Calibre2OPDS but as it generate static file no search was possible. Later I added an simple HTML catalog that should be usable on my Kobo. So COPS's main advantages are : * No need for many dependencies. * No need for a lot of CPU or RAM. * Not much code. * Search is available. * With Dropbox / owncloud it's very easy to have an up to date OPDS server. * It was fun to code. If you want to use the OPDS feed don't forget to specify feed.php at the end of your URL. \" \ + --no-cache --pull -t ${IMAGE}:${META_TAG} --platform=linux/amd64 \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + } + } + // Build MultiArch Docker containers for push to LS Repo + stage('Build-Multi') { + when { + allOf { + environment name: 'MULTIARCH', value: 'true' + expression { params.PACKAGE_CHECK == 'false' } + } + environment name: 'EXIT_STATUS', value: '' + } + parallel { + stage('Build X86') { + steps { + echo "Running on node: ${NODE_NAME}" + sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile" + sh "docker buildx build \ + --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ + --label \"org.opencontainers.image.authors=linuxserver.io\" \ + --label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-cops/packages\" \ + --label \"org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-cops\" \ + --label \"org.opencontainers.image.source=https://github.com/linuxserver/docker-cops\" \ + --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ + --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ + --label \"org.opencontainers.image.vendor=linuxserver.io\" \ + --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ + --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ + --label \"org.opencontainers.image.title=Cops\" \ + --label \"org.opencontainers.image.description=[Cops](http://blog.slucas.fr/en/oss/calibre-opds-php-server) by Sébastien Lucas, now maintained by MikesPub, stands for Calibre OPDS (and HTML) Php Server. COPS links to your Calibre library database and allows downloading and emailing of books directly from a web browser and provides a OPDS feed to connect to your devices. Changes in your Calibre library are reflected immediately in your COPS pages. See : [COPS's home](http://blog.slucas.fr/en/oss/calibre-opds-php-server) for more details. Don't forget to check the [Wiki](https://github.com/seblucas/cops/wiki). ## Why? (taken from the author's site) In my opinion Calibre is a marvelous tool but is too big and has too much dependencies to be used for its content server. That's the main reason why I coded this OPDS server. I needed a simple tool to be installed on a small server (Seagate Dockstar in my case). I initially thought of Calibre2OPDS but as it generate static file no search was possible. Later I added an simple HTML catalog that should be usable on my Kobo. So COPS's main advantages are : * No need for many dependencies. * No need for a lot of CPU or RAM. * Not much code. * Search is available. * With Dropbox / owncloud it's very easy to have an up to date OPDS server. * It was fun to code. If you want to use the OPDS feed don't forget to specify feed.php at the end of your URL. \" \ + --no-cache --pull -t ${IMAGE}:amd64-${META_TAG} --platform=linux/amd64 \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + } + } + stage('Build ARM64') { + agent { + label 'ARM64' + } + steps { + echo "Running on node: ${NODE_NAME}" + echo 'Logging into Github' + sh '''#! /bin/bash + echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin + ''' + sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile.aarch64" + sh "docker buildx build \ + --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ + --label \"org.opencontainers.image.authors=linuxserver.io\" \ + --label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-cops/packages\" \ + --label \"org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-cops\" \ + --label \"org.opencontainers.image.source=https://github.com/linuxserver/docker-cops\" \ + --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ + --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ + --label \"org.opencontainers.image.vendor=linuxserver.io\" \ + --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ + --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ + --label \"org.opencontainers.image.title=Cops\" \ + --label \"org.opencontainers.image.description=[Cops](http://blog.slucas.fr/en/oss/calibre-opds-php-server) by Sébastien Lucas, now maintained by MikesPub, stands for Calibre OPDS (and HTML) Php Server. COPS links to your Calibre library database and allows downloading and emailing of books directly from a web browser and provides a OPDS feed to connect to your devices. Changes in your Calibre library are reflected immediately in your COPS pages. See : [COPS's home](http://blog.slucas.fr/en/oss/calibre-opds-php-server) for more details. Don't forget to check the [Wiki](https://github.com/seblucas/cops/wiki). ## Why? (taken from the author's site) In my opinion Calibre is a marvelous tool but is too big and has too much dependencies to be used for its content server. That's the main reason why I coded this OPDS server. I needed a simple tool to be installed on a small server (Seagate Dockstar in my case). I initially thought of Calibre2OPDS but as it generate static file no search was possible. Later I added an simple HTML catalog that should be usable on my Kobo. So COPS's main advantages are : * No need for many dependencies. * No need for a lot of CPU or RAM. * Not much code. * Search is available. * With Dropbox / owncloud it's very easy to have an up to date OPDS server. * It was fun to code. If you want to use the OPDS feed don't forget to specify feed.php at the end of your URL. \" \ + --no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} --platform=linux/arm64 \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + sh "docker tag ${IMAGE}:arm64v8-${META_TAG} ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}" + retry(5) { + sh "docker push ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}" + } + sh '''#! /bin/bash + containers=$(docker ps -aq) + if [[ -n "${containers}" ]]; then + docker stop ${containers} + fi + docker system prune -af --volumes || : ''' + } + } + } + } + // Take the image we just built and dump package versions for comparison + stage('Update-packages') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'EXIT_STATUS', value: '' + } + steps { + sh '''#! /bin/bash + set -e + TEMPDIR=$(mktemp -d) + if [ "${MULTIARCH}" == "true" ] && [ "${PACKAGE_CHECK}" == "false" ]; then + LOCAL_CONTAINER=${IMAGE}:amd64-${META_TAG} + else + LOCAL_CONTAINER=${IMAGE}:${META_TAG} + fi + touch ${TEMPDIR}/package_versions.txt + docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock:ro \ + -v ${TEMPDIR}:/tmp \ + ghcr.io/anchore/syft:latest \ + ${LOCAL_CONTAINER} -o table=/tmp/package_versions.txt + NEW_PACKAGE_TAG=$(md5sum ${TEMPDIR}/package_versions.txt | cut -c1-8 ) + echo "Package tag sha from current packages in buit container is ${NEW_PACKAGE_TAG} comparing to old ${PACKAGE_TAG} from github" + if [ "${NEW_PACKAGE_TAG}" != "${PACKAGE_TAG}" ]; then + git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/${LS_REPO} + git --git-dir ${TEMPDIR}/${LS_REPO}/.git checkout -f master + cp ${TEMPDIR}/package_versions.txt ${TEMPDIR}/${LS_REPO}/ + cd ${TEMPDIR}/${LS_REPO}/ + wait + git add package_versions.txt + git commit -m 'Bot Updating Package Versions' + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + echo "true" > /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER} + echo "Package tag updated, stopping build process" + else + echo "false" > /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER} + echo "Package tag is same as previous continue with build process" + fi + rm -Rf ${TEMPDIR}''' + script{ + env.PACKAGE_UPDATED = sh( + script: '''cat /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER}''', + returnStdout: true).trim() + } + } + } + // Exit the build if the package file was just updated + stage('PACKAGE-exit') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'PACKAGE_UPDATED', value: 'true' + environment name: 'EXIT_STATUS', value: '' + } + steps { + script{ + env.EXIT_STATUS = 'ABORTED' + } + } + } + // Exit the build if this is just a package check and there are no changes to push + stage('PACKAGECHECK-exit') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'PACKAGE_UPDATED', value: 'false' + environment name: 'EXIT_STATUS', value: '' + expression { + params.PACKAGE_CHECK == 'true' + } + } + steps { + script{ + env.EXIT_STATUS = 'ABORTED' + } + } + } + /* ####### + Testing + ####### */ + // Run Container tests + stage('Test') { + when { + environment name: 'CI', value: 'true' + environment name: 'EXIT_STATUS', value: '' + } + steps { + withCredentials([ + string(credentialsId: 'ci-tests-s3-key-id', variable: 'S3_KEY'), + string(credentialsId: 'ci-tests-s3-secret-access-key ', variable: 'S3_SECRET') + ]) { + script{ + env.CI_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/index.html' + env.CI_JSON_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/report.json' + } + sh '''#! /bin/bash + set -e + docker pull ghcr.io/linuxserver/ci:latest + if [ "${MULTIARCH}" == "true" ]; then + docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} + docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} + fi + docker run --rm \ + --shm-size=1gb \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -e IMAGE=\"${IMAGE}\" \ + -e DELAY_START=\"${CI_DELAY}\" \ + -e TAGS=\"${CI_TAGS}\" \ + -e META_TAG=\"${META_TAG}\" \ + -e PORT=\"${CI_PORT}\" \ + -e SSL=\"${CI_SSL}\" \ + -e BASE=\"${DIST_IMAGE}\" \ + -e SECRET_KEY=\"${S3_SECRET}\" \ + -e ACCESS_KEY=\"${S3_KEY}\" \ + -e DOCKER_ENV=\"${CI_DOCKERENV}\" \ + -e WEB_SCREENSHOT=\"${CI_WEB}\" \ + -e WEB_AUTH=\"${CI_AUTH}\" \ + -e WEB_PATH=\"${CI_WEBPATH}\" \ + -t ghcr.io/linuxserver/ci:latest \ + python3 test_build.py''' + } + } + } + /* ################## + Release Logic + ################## */ + // If this is an amd64 only image only push a single image + stage('Docker-Push-Single') { + when { + environment name: 'MULTIARCH', value: 'false' + environment name: 'EXIT_STATUS', value: '' + } + steps { + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', + usernameVariable: 'DOCKERUSER', + passwordVariable: 'DOCKERPASS' + ], + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: 'Quay.io-Robot', + usernameVariable: 'QUAYUSER', + passwordVariable: 'QUAYPASS' + ] + ]) { + retry(5) { + sh '''#! /bin/bash + set -e + echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin + 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 + for PUSHIMAGE in "${GITHUBIMAGE}" "${GITLABIMAGE}" "${QUAYIMAGE}" "${IMAGE}"; do + docker tag ${IMAGE}:${META_TAG} ${PUSHIMAGE}:${META_TAG} + docker tag ${PUSHIMAGE}:${META_TAG} ${PUSHIMAGE}:latest + docker tag ${PUSHIMAGE}:${META_TAG} ${PUSHIMAGE}:${EXT_RELEASE_TAG} + if [ -n "${SEMVER}" ]; then + docker tag ${PUSHIMAGE}:${META_TAG} ${PUSHIMAGE}:${SEMVER} + fi + docker push ${PUSHIMAGE}:latest + docker push ${PUSHIMAGE}:${META_TAG} + docker push ${PUSHIMAGE}:${EXT_RELEASE_TAG} + if [ -n "${SEMVER}" ]; then + docker push ${PUSHIMAGE}:${SEMVER} + fi + done + ''' + } + } + } + } + // If this is a multi arch release push all images and define the manifest + stage('Docker-Push-Multi') { + when { + environment name: 'MULTIARCH', value: 'true' + environment name: 'EXIT_STATUS', value: '' + } + steps { + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', + usernameVariable: 'DOCKERUSER', + passwordVariable: 'DOCKERPASS' + ], + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: 'Quay.io-Robot', + usernameVariable: 'QUAYUSER', + passwordVariable: 'QUAYPASS' + ] + ]) { + retry(5) { + sh '''#! /bin/bash + set -e + echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin + 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 [ "${CI}" == "false" ]; then + docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} + docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} + fi + for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do + docker tag ${IMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} + docker tag ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-latest + docker tag ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} + docker tag ${IMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} + docker tag ${MANIFESTIMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-latest + docker tag ${MANIFESTIMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} + if [ -n "${SEMVER}" ]; then + docker tag ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-${SEMVER} + docker tag ${MANIFESTIMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${SEMVER} + fi + docker push ${MANIFESTIMAGE}:amd64-${META_TAG} + docker push ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} + docker push ${MANIFESTIMAGE}:amd64-latest + docker push ${MANIFESTIMAGE}:arm64v8-${META_TAG} + docker push ${MANIFESTIMAGE}:arm64v8-latest + docker push ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} + if [ -n "${SEMVER}" ]; then + docker push ${MANIFESTIMAGE}:amd64-${SEMVER} + docker push ${MANIFESTIMAGE}:arm64v8-${SEMVER} + fi + docker manifest push --purge ${MANIFESTIMAGE}:latest || : + docker manifest create ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:amd64-latest ${MANIFESTIMAGE}:arm64v8-latest + docker manifest annotate ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:arm64v8-latest --os linux --arch arm64 --variant v8 + docker manifest push --purge ${MANIFESTIMAGE}:${META_TAG} || : + docker manifest create ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} + docker manifest annotate ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} --os linux --arch arm64 --variant v8 + docker manifest push --purge ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} || : + docker manifest create ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} + docker manifest annotate ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} --os linux --arch arm64 --variant v8 + if [ -n "${SEMVER}" ]; then + docker manifest push --purge ${MANIFESTIMAGE}:${SEMVER} || : + docker manifest create ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} + docker manifest annotate ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} --os linux --arch arm64 --variant v8 + fi + token=$(curl -sX GET "https://ghcr.io/token?scope=repository%3Alinuxserver%2F${CONTAINER_NAME}%3Apull" | jq -r '.token') + digest=$(curl -s \ + --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ + --header "Authorization: Bearer ${token}" \ + "https://ghcr.io/v2/linuxserver/${CONTAINER_NAME}/manifests/arm32v7-latest") + if [[ $(echo "$digest" | jq -r '.layers') != "null" ]]; then + docker manifest push --purge ${MANIFESTIMAGE}:arm32v7-latest || : + docker manifest create ${MANIFESTIMAGE}:arm32v7-latest ${MANIFESTIMAGE}:amd64-latest + docker manifest push --purge ${MANIFESTIMAGE}:arm32v7-latest + fi + docker manifest push --purge ${MANIFESTIMAGE}:latest + docker manifest push --purge ${MANIFESTIMAGE}:${META_TAG} + docker manifest push --purge ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} + if [ -n "${SEMVER}" ]; then + docker manifest push --purge ${MANIFESTIMAGE}:${SEMVER} + fi + done + ''' + } + } + } + } + // If this is a public release tag it in the LS Github + stage('Github-Tag-Push-Release') { + when { + branch "master" + expression { + env.LS_RELEASE != env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + } + environment name: 'CHANGE_ID', value: '' + environment name: 'EXIT_STATUS', value: '' + } + steps { + 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}'",\ + "object": "'${COMMIT_SHA}'",\ + "message": "Tagging Release '${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}' to master",\ + "type": "commit",\ + "tagger": {"name": "LinuxServer Jenkins","email": "jenkins@linuxserver.io","date": "'${GITHUB_DATE}'"}}' ''' + echo "Pushing New release for Tag" + sh '''#! /bin/bash + curl -H "Authorization: token ${GITHUB_TOKEN}" -s https://api.github.com/repos/${EXT_USER}/${EXT_REPO}/releases/latest | jq '. |.body' | sed 's:^.\\(.*\\).$:\\1:' > releasebody.json + echo '{"tag_name":"'${META_TAG}'",\ + "target_commitish": "master",\ + "name": "'${META_TAG}'",\ + "body": "**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**'${EXT_REPO}' Changes:**\\n\\n' > start + printf '","draft": false,"prerelease": false}' >> releasebody.json + paste -d'\\0' start releasebody.json > 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''' + } + } + // Use helper container to sync the current README on master to the dockerhub endpoint + stage('Sync-README') { + when { + environment name: 'CHANGE_ID', value: '' + environment name: 'EXIT_STATUS', value: '' + } + steps { + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', + usernameVariable: 'DOCKERUSER', + passwordVariable: 'DOCKERPASS' + ] + ]) { + sh '''#! /bin/bash + set -e + TEMPDIR=$(mktemp -d) + docker pull ghcr.io/linuxserver/jenkins-builder:latest + docker run --rm -e CONTAINER_NAME=${CONTAINER_NAME} -e GITHUB_BRANCH="${BRANCH_NAME}" -v ${TEMPDIR}:/ansible/jenkins ghcr.io/linuxserver/jenkins-builder:latest + docker pull ghcr.io/linuxserver/readme-sync + docker run --rm=true \ + -e DOCKERHUB_USERNAME=$DOCKERUSER \ + -e DOCKERHUB_PASSWORD=$DOCKERPASS \ + -e GIT_REPOSITORY=${LS_USER}/${LS_REPO} \ + -e DOCKER_REPOSITORY=${IMAGE} \ + -e GIT_BRANCH=master \ + -v ${TEMPDIR}/docker-${CONTAINER_NAME}:/mnt \ + ghcr.io/linuxserver/readme-sync bash -c 'node sync' + rm -Rf ${TEMPDIR} ''' + } + } + } + // If this is a Pull request send the CI link as a comment on it + stage('Pull Request Comment') { + when { + not {environment name: 'CHANGE_ID', value: ''} + environment name: 'EXIT_STATUS', value: '' + } + steps { + sh '''#! /bin/bash + # Function to retrieve JSON data from URL + get_json() { + local url="$1" + local response=$(curl -s "$url") + if [ $? -ne 0 ]; then + echo "Failed to retrieve JSON data from $url" + return 1 + fi + local json=$(echo "$response" | jq .) + if [ $? -ne 0 ]; then + echo "Failed to parse JSON data from $url" + return 1 + fi + echo "$json" + } + + build_table() { + local data="$1" + + # Get the keys in the JSON data + local keys=$(echo "$data" | jq -r 'to_entries | map(.key) | .[]') + + # Check if keys are empty + if [ -z "$keys" ]; then + echo "JSON report data does not contain any keys or the report does not exist." + return 1 + fi + + # Build table header + local header="| Tag | Passed |\\n| --- | --- |\\n" + + # Loop through the JSON data to build the table rows + local rows="" + for build in $keys; do + local status=$(echo "$data" | jq -r ".[\\"$build\\"].test_success") + if [ "$status" = "true" ]; then + status="✅" + else + status="❌" + fi + local row="| "$build" | "$status" |\\n" + rows="${rows}${row}" + done + + local table="${header}${rows}" + local escaped_table=$(echo "$table" | sed 's/\"/\\\\"/g') + echo "$escaped_table" + } + + if [[ "${CI}" = "true" ]]; then + # Retrieve JSON data from URL + data=$(get_json "$CI_JSON_URL") + # Create table from JSON data + table=$(build_table "$data") + echo -e "$table" + + curl -X POST -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \ + -d "{\\"body\\": \\"I am a bot, here are the test results for this PR: \\n${CI_URL}\\n${SHELLCHECK_URL}\\n${table}\\"}" + else + curl -X POST -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \ + -d "{\\"body\\": \\"I am a bot, here is the pushed image/manifest for this PR: \\n\\n\\`${GITHUBIMAGE}:${META_TAG}\\`\\"}" + fi + ''' + + } + } + } + /* ###################### + Send status to Discord + ###################### */ + post { + always { + script{ + if (env.EXIT_STATUS == "ABORTED"){ + sh 'echo "build aborted"' + } + else if (currentBuild.currentResult == "SUCCESS"){ + sh ''' curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/jenkins-avatar.png","embeds": [{"color": 1681177,\ + "description": "**Build:** '${BUILD_NUMBER}'\\n**CI Results:** '${CI_URL}'\\n**ShellCheck Results:** '${SHELLCHECK_URL}'\\n**Status:** Success\\n**Job:** '${RUN_DISPLAY_URL}'\\n**Change:** '${CODE_URL}'\\n**External Release:**: '${RELEASE_LINK}'\\n**DockerHub:** '${DOCKERHUB_LINK}'\\n"}],\ + "username": "Jenkins"}' ${BUILDS_DISCORD} ''' + } + else { + sh ''' curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/jenkins-avatar.png","embeds": [{"color": 16711680,\ + "description": "**Build:** '${BUILD_NUMBER}'\\n**CI Results:** '${CI_URL}'\\n**ShellCheck Results:** '${SHELLCHECK_URL}'\\n**Status:** failure\\n**Job:** '${RUN_DISPLAY_URL}'\\n**Change:** '${CODE_URL}'\\n**External Release:**: '${RELEASE_LINK}'\\n**DockerHub:** '${DOCKERHUB_LINK}'\\n"}],\ + "username": "Jenkins"}' ${BUILDS_DISCORD} ''' + } + } + } + cleanup { + sh '''#! /bin/bash + echo "Performing docker system prune!!" + containers=$(docker ps -aq) + if [[ -n "${containers}" ]]; then + docker stop ${containers} + fi + docker system prune -af --volumes || : + ''' + cleanWs() + } + } +} diff --git a/README.md b/README.md index 8622a48..3f94778 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ Find us at: * [GitHub](https://github.com/linuxserver) - view the source for all of our repositories. * [Open Collective](https://opencollective.com/linuxserver) - please consider helping us by either donating or contributing to our budget +# [linuxserver/cops](https://github.com/linuxserver/docker-cops) + [![Scarf.io pulls](https://scarf.sh/installs-badge/linuxserver-ci/linuxserver%2Fcops?color=94398d&label-color=555555&logo-color=ffffff&style=for-the-badge&package-type=docker)](https://scarf.sh/gateway/linuxserver-ci/docker/linuxserver%2Fcops) [![GitHub Stars](https://img.shields.io/github/stars/linuxserver/docker-cops.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-cops) [![GitHub Release](https://img.shields.io/github/release/linuxserver/docker-cops.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-cops/releases) @@ -85,6 +87,7 @@ The architectures supported by this image are: | :----: | :----: | ---- | | x86-64 | ✅ | amd64-\<version tag\> | | arm64 | ✅ | arm64v8-\<version tag\> | +| armhf | ❌ | | ## Application Setup diff --git a/jenkins-vars.yml b/jenkins-vars.yml index 23a5174..98decab 100644 --- a/jenkins-vars.yml +++ b/jenkins-vars.yml @@ -5,9 +5,9 @@ project_name: docker-cops external_type: github_stable release_type: stable release_tag: latest -ls_branch: mikespub +ls_branch: master repo_vars: - - EXT_GIT_BRANCH = 'master' + - EXT_GIT_BRANCH = 'main' - EXT_USER = 'mikespub-org' - EXT_REPO = 'seblucas-cops' - BUILD_VERSION_ARG = 'COPS_RELEASE'