| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 1 | # use the verse rocker image, as it contains tidyverse, devtools and some texlive |
| Marc Kupietz | d0e1b3a | 2023-06-16 15:12:25 +0200 | [diff] [blame] | 2 | image: rocker/tidyverse |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 3 | |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 4 | variables: |
| 5 | # Set `CCACHE_BASEDIR` and `CCACHE_DIR` to point `ccache` towards the cached |
| 6 | # path on the gitlab-runner. This enables to cache the output of `ccache` |
| 7 | # between various runs. |
| 8 | CCACHE_BASEDIR: "${CI_PROJECT_DIR}" |
| 9 | CCACHE_DIR: "${CI_PROJECT_DIR}/ccache" |
| 10 | # Set `ccache` to `content` to prevent rebuilding of the CI/CD containers to |
| 11 | # trigger a recreate of the cache. By using `content` the compiler's `mtime` |
| 12 | # is not considered as part of the hash. |
| 13 | CCACHE_COMPILERCHECK: "content" |
| 14 | # Enable caching for `apt-get`. |
| 15 | APT_CACHE_DIR: "${CI_PROJECT_DIR}/apt-cache" |
| 16 | # Export `noninteractive` frontend to prevent requesting user input. |
| 17 | DEBIAN_FRONTEND: "noninteractive" |
| 18 | R_LIBS_USER: "RLIB/library" |
| 19 | SOURCE_FILE: "inst/rmarkdown/templates/posterdown_ids/skeleton/skeleton.Rmd" |
| 20 | |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 21 | # define stages of runner. at the moment, |
| 22 | # just build (no test or deploy). |
| 23 | stages: |
| 24 | - build |
| 25 | |
| 26 | build-job: |
| 27 | stage: build |
| 28 | |
| 29 | cache: |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 30 | key: posterdown-ids |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 31 | paths: |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 32 | - cache |
| 33 | - apt-cache/ |
| 34 | - ccache/ |
| 35 | - RLIB/library/ |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 36 | |
| 37 | artifacts: |
| 38 | paths: |
| 39 | - "target/*" |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 40 | |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 41 | before_script: |
| 42 | - source `find .. -name section_helper.sh` |
| 43 | |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 44 | - start_section apt_mirrors "Configuring apt mirror and retries" |
| 45 | - . /etc/os-release || true |
| 46 | - | |
| 47 | # Prefer mirror lists (automatic, resilient). Optionally force a German mirror |
| 48 | # by setting APT_FORCE_DE_MIRROR=1 in CI/CD variables if you want a fixed DE mirror. |
| 49 | # Handle both classic sources.list and Deb822 .sources files. |
| 50 | set -eu |
| 51 | APT_FILES=(/etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources) |
| 52 | # shellcheck disable=SC2068 |
| 53 | APT_FILES=( ${APT_FILES[@]} ) |
| 54 | echo "--- os-release (selected) ---" |
| 55 | grep -E '^(ID|VERSION_ID|VERSION_CODENAME|UBUNTU_CODENAME)=' /etc/os-release || true |
| 56 | echo "--- resolved APT source files ---" |
| 57 | for f in ${APT_FILES[@]}; do [ -e "$f" ] && echo " - $f"; done |
| 58 | echo "--- env summary ---" |
| 59 | echo "APT_FORCE_DE_MIRROR=${APT_FORCE_DE_MIRROR:-} ID=${ID:-} VERSION_CODENAME=${VERSION_CODENAME:-} UBUNTU_CODENAME=${UBUNTU_CODENAME:-}" |
| 60 | echo "--- apt sources (pre) ---" |
| 61 | for f in ${APT_FILES[@]}; do |
| 62 | [ -e "$f" ] || continue |
| 63 | echo "### $f" |
| 64 | grep -nE '^(deb|deb-src)|^(Types|URIs|Suites|Components)=' "$f" || sed -n '1,40p' "$f" || true |
| 65 | done |
| 66 | echo "--- rewrite mode decision ---" |
| 67 | AUTOPICK="${APT_AUTOPICK_MIRROR:-}" |
| 68 | if [ "${APT_FORCE_DE_MIRROR:-}" = "auto" ]; then AUTOPICK=1; fi |
| 69 | if [ "${AUTOPICK}" = "1" ]; then |
| 70 | echo "Mode=AUTO_PICK OS=${ID:-unknown}" |
| 71 | if [ "${ID:-}" = "ubuntu" ] && command -v curl >/dev/null 2>&1; then |
| 72 | CODE_NAME="${UBUNTU_CODENAME:-${VERSION_CODENAME:-}}" |
| 73 | LIST_URL="https://mirrors.ubuntu.com/mirrors.txt" |
| 74 | echo "Fetching mirror list: $LIST_URL" |
| 75 | MIRRORS=$(curl -fsSL "$LIST_URL" | grep -E '^https?://.+' | sed 's#/*$##' | head -n 20 || true) |
| 76 | BEST_URL=""; BEST_TIME="9999" |
| 77 | echo "Testing up to 20 mirrors for ${CODE_NAME} InRelease" |
| 78 | for m in $MIRRORS; do |
| 79 | TEST_URL="$m/dists/${CODE_NAME}/InRelease" |
| 80 | RES=$(curl -m 3 --connect-timeout 2 -o /dev/null -s -w '%{time_total} %{http_code}' "$TEST_URL" || echo "9.999 000") |
| 81 | TME=${RES%% *}; CODE=${RES##* } |
| 82 | echo " $(printf '%6s' "$TME")s $CODE $m" |
| 83 | if [ "$CODE" = "200" ]; then |
| 84 | BETTER=$(awk -v a="$TME" -v b="$BEST_TIME" 'BEGIN{print (a<b)?"1":"0"}') |
| 85 | if [ "$BETTER" = "1" ]; then BEST_TIME="$TME"; BEST_URL="$m"; fi |
| 86 | fi |
| 87 | done |
| 88 | if [ -n "$BEST_URL" ]; then |
| 89 | MIRROR_URL="${BEST_URL}" |
| 90 | echo "Selected fastest: $MIRROR_URL (time=${BEST_TIME}s)" |
| 91 | for f in ${APT_FILES[@]}; do |
| 92 | [ -e "$f" ] || continue |
| 93 | # Replace any Ubuntu archive base with selected mirror |
| 94 | sed -i -E "s#https?://[^ ]*/ubuntu#${MIRROR_URL}#g" "$f" || true |
| 95 | sed -i -E "s#mirror://mirrors\.ubuntu\.com/mirrors\.txt#${MIRROR_URL}#g" "$f" || true |
| 96 | done |
| 97 | else |
| 98 | echo "Autopick failed to find a working mirror; falling back to mirror list." |
| 99 | AUTOPICK=0 |
| 100 | fi |
| 101 | else |
| 102 | echo "Autopick not available (non-Ubuntu or curl missing); falling back." |
| 103 | AUTOPICK=0 |
| 104 | fi |
| 105 | fi |
| 106 | if [ "${AUTOPICK}" != "1" ] && [ "${APT_FORCE_DE_MIRROR:-}" = "1" ]; then |
| 107 | echo "Mode=FORCED_MIRROR OS=${ID:-unknown}" |
| 108 | if [ "${ID:-}" = "ubuntu" ]; then |
| 109 | MIRROR_URL="http://de.archive.ubuntu.com/ubuntu" |
| 110 | for f in ${APT_FILES[@]}; do |
| 111 | [ -e "$f" ] || continue |
| 112 | sed -i -E "s#https?://[^ ]*ubuntu.com/ubuntu#${MIRROR_URL}#g" "$f" || true |
| 113 | sed -i -E "s#mirror://mirrors\.ubuntu\.com/mirrors\.txt#${MIRROR_URL}#g" "$f" || true |
| 114 | done |
| 115 | elif [ "${ID:-}" = "debian" ]; then |
| 116 | MIRROR_URL="http://ftp.de.debian.org/debian" |
| 117 | for f in ${APT_FILES[@]}; do |
| 118 | [ -e "$f" ] || continue |
| 119 | sed -i -E "s#https?://(deb|ftp)[^ ]*debian.org/debian#${MIRROR_URL}#g" "$f" || true |
| 120 | sed -i -E "s#mirror://mirrors\.debian\.org/debian#${MIRROR_URL}#g" "$f" || true |
| 121 | done |
| 122 | fi |
| 123 | elif [ "${AUTOPICK}" != "1" ]; then |
| 124 | echo "Mode=MIRROR_LIST OS=${ID:-unknown}" |
| 125 | if [ "${ID:-}" = "ubuntu" ]; then |
| 126 | for f in ${APT_FILES[@]}; do [ -e "$f" ] && sed -i -E 's#https?://[^ ]*ubuntu.com/ubuntu#mirror://mirrors.ubuntu.com/mirrors.txt#g' "$f" || true; done |
| 127 | elif [ "${ID:-}" = "debian" ]; then |
| 128 | for f in ${APT_FILES[@]}; do [ -e "$f" ] && sed -i -E 's#https?://(deb|ftp)[^ ]*debian.org/debian#mirror://mirrors.debian.org/debian#g' "$f" || true; done |
| 129 | fi |
| 130 | fi |
| 131 | echo "--- apt sources (post) ---" |
| 132 | for f in ${APT_FILES[@]}; do |
| 133 | [ -e "$f" ] || continue |
| 134 | echo "### $f" |
| 135 | grep -nE '^(deb|deb-src)|^(Types|URIs|Suites|Components)=' "$f" || sed -n '1,40p' "$f" || true |
| 136 | done |
| 137 | # Show which mirror hosts remain after rewriting, to aid debugging |
| 138 | echo "APT_FORCE_DE_MIRROR=${APT_FORCE_DE_MIRROR:-} ID=${ID:-} VERSION_CODENAME=${VERSION_CODENAME:-}" |
| 139 | grep -R "archive\.ubuntu\.com/ubuntu\|ubuntu\.com/ubuntu\|debian\.org/debian\|mirrors\.ubuntu\.com\|mirrors\.debian\.org" -n /etc/apt || true |
| 140 | echo "--- apt origins (apt-cache policy) ---" |
| 141 | apt-cache policy | sed -n '1,120p' || true |
| 142 | printf 'Acquire::Retries "5";\nAcquire::http::Timeout "30";\nAcquire::https::Timeout "30";\nAcquire::http::Pipeline-Depth "0";\n' > /etc/apt/apt.conf.d/99retries |
| 143 | - end_section apt_mirrors |
| 144 | |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 145 | - start_section install_linux_packages "Installing missing Linux packages" |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 146 | - mkdir -pv $APT_CACHE_DIR ccache $R_LIBS_USER |
| 147 | - apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 update |
| Marc Kupietz | c0ae3c2 | 2026-07-17 11:47:07 +0200 | [diff] [blame^] | 148 | - apt-get install --no-install-recommends -o dir::cache::archives="$APT_CACHE_DIR" -y libasound2t64 npm curl ccache libvulkan1 libu2f-udev fonts-liberation build-essential libglpk40 libcurl4-gnutls-dev libxml2-dev libsodium-dev libsecret-1-dev libfontconfig1-dev libssl-dev libxt6 libpq-dev imagemagick ghostscript inkscape scour poppler-utils qpdf fonts-stix |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 149 | # The distro Node (18, EOL) is too old for current tooling. Install the |
| 150 | # current Node.js LTS (24.x) from the official tarball into /usr/local, which |
| 151 | # precedes /usr/bin on PATH so `node`/`npx` resolve to it. We deliberately do |
| 152 | # NOT use NodeSource/apt: its `nodejs` package does not satisfy `nodejs:any`, |
| 153 | # which breaks the distro `libnode-dev`/`node-acorn` sysdeps pak installs later. |
| 154 | - NODE_TARBALL=$(curl -fsSL https://nodejs.org/dist/latest-v24.x/ | grep -oE 'node-v24\.[0-9]+\.[0-9]+-linux-x64\.tar\.gz' | head -n1) |
| 155 | - curl -fsSL "https://nodejs.org/dist/latest-v24.x/$NODE_TARBALL" | tar -xz -C /usr/local --strip-components=1 |
| 156 | - node --version |
| Marc Kupietz | ea92ad9 | 2025-03-23 18:16:06 +0100 | [diff] [blame] | 157 | - npx @puppeteer/browsers install chrome-headless-shell@stable |
| 158 | - export CHROME=$(find ~+ -name chrome-headless-shell -type f) |
| 159 | - echo "CHROME=$CHROME" |
| 160 | - ln -s $CHROME /usr/bin/google-chrome |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 161 | - ln -s $(which ccache) /usr/local/sbin/gcc |
| 162 | - ln -s $(which ccache) /usr/local/sbin/g++ |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 163 | - locale-gen de_DE.utf8 en_GB.utf8 en_US.utf8 |
| 164 | - end_section install_linux_packages |
| 165 | |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 166 | - start_section testing_chromium "Testing chrome" |
| 167 | - google-chrome --version |
| 168 | - end_section testing_chromium |
| 169 | |
| 170 | - start_section install_fonts "Installing Fira and emoji fonts" |
| Marc Kupietz | 78b0871 | 2025-02-02 22:10:18 +0100 | [diff] [blame] | 171 | - curl -Ls https://github.com/mozilla/Fira/archive/refs/tags/4.202.tar.gz | tar -C /usr/share/fonts -zx --wildcards "*.otf" |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 172 | - apt-get install --no-install-recommends -o dir::cache::archives="$APT_CACHE_DIR" -y fonts-noto-color-emoji fonts-symbola |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 173 | - fc-cache |
| 174 | - end_section install_fonts |
| 175 | |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 176 | - start_section install_r_packages "Installing missing R packages" |
| Marc Kupietz | 78b0871 | 2025-02-02 22:10:18 +0100 | [diff] [blame] | 177 | # - echo -e 'local({r <- getOption("repos")\n r["CRAN"] <- "https://cloud.r-project.org"\n options(repos=r)})' > ~/.Rprofile |
| Marc Kupietz | d69b9fa | 2024-05-02 12:46:35 +0200 | [diff] [blame] | 178 | - echo "options(Ncpus=$(nproc))" >> ~/.Rprofile |
| Marc Kupietz | 78b0871 | 2025-02-02 22:10:18 +0100 | [diff] [blame] | 179 | - R -e "install.packages('pak', dependencies=TRUE)" |
| Marc Kupietz | d280ea6 | 2025-06-17 16:52:55 +0200 | [diff] [blame] | 180 | - R -e "pak::pak(c('devtools', 'scales', 'sp', 'raster', 'kableExtra', 'DT', 'svglite', 'qrcode', 'ggthemes', 'patchwork', 'pagedown'), dependencies=TRUE)" |
| Marc Kupietz | 8945875 | 2024-05-02 12:17:46 +0200 | [diff] [blame] | 181 | - R -e 'devtools::install_git("https://korap.ids-mannheim.de/gerrit/IDS-Mannheim/idsThemeR", dependencies=TRUE)' |
| 182 | - R -e 'devtools::install_git("https://korap.ids-mannheim.de/gerrit/IDS-Mannheim/posterdown", dependencies=TRUE)' |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 183 | - end_section install_r_packages |
| 184 | |
| Marc Kupietz | e074d05 | 2025-06-20 13:50:10 +0200 | [diff] [blame] | 185 | - start_section testing_html2pdf "Testing PDF export" |
| 186 | - ./ci/html2pdf https://google.com |
| 187 | - ls -l ./google.pdf |
| 188 | - end_section testing_html2pdf |
| 189 | |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 190 | script: |
| Marc Kupietz | a39d0cc | 2024-05-31 12:45:45 +0200 | [diff] [blame] | 191 | - start_section installing "Installing posterdown.ids" |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 192 | - R -e 'devtools::install()' |
| 193 | - end_section installing |
| 194 | - start_section render "Generating demo artifacts" |
| Marc Kupietz | f0eeb46 | 2024-05-31 16:13:55 +0200 | [diff] [blame] | 195 | - R_CACHE_ROOTPATH=./cache R -e "require(rmarkdown); render('$SOURCE_FILE', output_format='posterdown.ids::posterdown_ids', output_dir='target')" |
| 196 | - export SVG=target/$(basename $SOURCE_FILE .Rmd).svg |
| 197 | - export HTML=target/$(basename $SOURCE_FILE .Rmd).html |
| 198 | - export PDF=target/$(basename $SOURCE_FILE .Rmd).pdf |
| 199 | - ./ci/html2pdf $HTML $PDF 1 |
| Marc Kupietz | c0ae3c2 | 2026-07-17 11:47:07 +0200 | [diff] [blame^] | 200 | # Variant for printing on fabric, where solid black bleeds out: replace all |
| 201 | # vector black by 15% grey (keeps QR codes scannable and text crisp). |
| 202 | - ./ci/pdf-lighten-black $PDF target/$(basename $SOURCE_FILE .Rmd)_fabric.pdf |
| Marc Kupietz | d13544d | 2026-07-17 11:04:45 +0200 | [diff] [blame] | 203 | - gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -sPAPERSIZE=a1 -dFIXEDMEDIA -dPDFFitPage -sOutputFile=target/$(basename $SOURCE_FILE .Rmd)_a1.pdf $PDF |
| Marc Kupietz | f0eeb46 | 2024-05-31 16:13:55 +0200 | [diff] [blame] | 204 | - inkscape -b white --pdf-poppler -o $SVG $PDF || true |
| 205 | - scour -i $SVG -o target/skeleton_optimized.svg --enable-viewboxing --enable-id-stripping --shorten-ids --indent=none |
| Marc Kupietz | ce1aa0c | 2023-06-15 07:50:23 +0200 | [diff] [blame] | 206 | - end_section render |