blob: 472002e0d8ef4c83f7c03ca5474b1069500ecf6a [file] [log] [blame]
Marc Kupietzce1aa0c2023-06-15 07:50:23 +02001# use the verse rocker image, as it contains tidyverse, devtools and some texlive
Marc Kupietzd0e1b3a2023-06-16 15:12:25 +02002image: rocker/tidyverse
Marc Kupietzce1aa0c2023-06-15 07:50:23 +02003
Marc Kupietzd13544d2026-07-17 11:04:45 +02004variables:
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 Kupietzce1aa0c2023-06-15 07:50:23 +020021# define stages of runner. at the moment,
22# just build (no test or deploy).
23stages:
24 - build
25
26build-job:
27 stage: build
28
29 cache:
Marc Kupietzd13544d2026-07-17 11:04:45 +020030 key: posterdown-ids
Marc Kupietzce1aa0c2023-06-15 07:50:23 +020031 paths:
Marc Kupietzd13544d2026-07-17 11:04:45 +020032 - cache
33 - apt-cache/
34 - ccache/
35 - RLIB/library/
Marc Kupietzce1aa0c2023-06-15 07:50:23 +020036
37 artifacts:
38 paths:
39 - "target/*"
Marc Kupietzd13544d2026-07-17 11:04:45 +020040
Marc Kupietzce1aa0c2023-06-15 07:50:23 +020041 before_script:
42 - source `find .. -name section_helper.sh`
43
Marc Kupietzd13544d2026-07-17 11:04:45 +020044 - 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 Kupietzce1aa0c2023-06-15 07:50:23 +0200145 - start_section install_linux_packages "Installing missing Linux packages"
Marc Kupietzd13544d2026-07-17 11:04:45 +0200146 - 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 Kupietza01aee12026-08-04 10:33:17 +0200148 - 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 texlive-extra-utils texlive-latex-extra fonts-stix
149 - command -v pdfjam
150 - kpsewhich pdfpages.sty
Marc Kupietzd13544d2026-07-17 11:04:45 +0200151 # The distro Node (18, EOL) is too old for current tooling. Install the
152 # current Node.js LTS (24.x) from the official tarball into /usr/local, which
153 # precedes /usr/bin on PATH so `node`/`npx` resolve to it. We deliberately do
154 # NOT use NodeSource/apt: its `nodejs` package does not satisfy `nodejs:any`,
155 # which breaks the distro `libnode-dev`/`node-acorn` sysdeps pak installs later.
156 - 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)
157 - curl -fsSL "https://nodejs.org/dist/latest-v24.x/$NODE_TARBALL" | tar -xz -C /usr/local --strip-components=1
158 - node --version
Marc Kupietzea92ad92025-03-23 18:16:06 +0100159 - npx @puppeteer/browsers install chrome-headless-shell@stable
160 - export CHROME=$(find ~+ -name chrome-headless-shell -type f)
161 - echo "CHROME=$CHROME"
162 - ln -s $CHROME /usr/bin/google-chrome
Marc Kupietzd13544d2026-07-17 11:04:45 +0200163 - ln -s $(which ccache) /usr/local/sbin/gcc
164 - ln -s $(which ccache) /usr/local/sbin/g++
Marc Kupietzce1aa0c2023-06-15 07:50:23 +0200165 - locale-gen de_DE.utf8 en_GB.utf8 en_US.utf8
166 - end_section install_linux_packages
167
Marc Kupietzd13544d2026-07-17 11:04:45 +0200168 - start_section testing_chromium "Testing chrome"
169 - google-chrome --version
170 - end_section testing_chromium
171
Marc Kupietz81716692026-07-23 14:56:31 +0200172 - start_section install_fonts "Installing Fira, Twemoji and emoji fonts"
Marc Kupietz78b08712025-02-02 22:10:18 +0100173 - curl -Ls https://github.com/mozilla/Fira/archive/refs/tags/4.202.tar.gz | tar -C /usr/share/fonts -zx --wildcards "*.otf"
Marc Kupietza487fb72026-07-23 15:16:59 +0200174 - apt-get install --no-install-recommends -o dir::cache::archives="$APT_CACHE_DIR" -y rpm2cpio cpio fonts-noto-color-emoji fonts-symbola
175 # Fedora's twitter-twemoji-fonts package ships a CBDT/CBLC (bitmap) build
176 # of Twemoji. Use that rather than upstream's own SVGinOT release: Chrome
177 # renders SVGinOT in color on screen, but its print-to-PDF path silently
178 # falls back to the font's monochrome outline glyphs for that format --
179 # CBDT/CBLC (like Noto Color Emoji) embeds correctly as a color PDF font.
180 - curl -sLo /tmp/twemoji.rpm https://dl.fedoraproject.org/pub/fedora/linux/releases/44/Everything/x86_64/os/Packages/t/twitter-twemoji-fonts-14.0.2-10.fc44.noarch.rpm
181 - (cd / && rpm2cpio /tmp/twemoji.rpm | cpio -idm ./usr/share/fonts/twemoji/Twemoji.ttf)
Marc Kupietzce1aa0c2023-06-15 07:50:23 +0200182 - fc-cache
183 - end_section install_fonts
184
Marc Kupietzce1aa0c2023-06-15 07:50:23 +0200185 - start_section install_r_packages "Installing missing R packages"
Marc Kupietz78b08712025-02-02 22:10:18 +0100186# - echo -e 'local({r <- getOption("repos")\n r["CRAN"] <- "https://cloud.r-project.org"\n options(repos=r)})' > ~/.Rprofile
Marc Kupietzd69b9fa2024-05-02 12:46:35 +0200187 - echo "options(Ncpus=$(nproc))" >> ~/.Rprofile
Marc Kupietz78b08712025-02-02 22:10:18 +0100188 - R -e "install.packages('pak', dependencies=TRUE)"
Marc Kupietzd280ea62025-06-17 16:52:55 +0200189 - R -e "pak::pak(c('devtools', 'scales', 'sp', 'raster', 'kableExtra', 'DT', 'svglite', 'qrcode', 'ggthemes', 'patchwork', 'pagedown'), dependencies=TRUE)"
Marc Kupietz89458752024-05-02 12:17:46 +0200190 - R -e 'devtools::install_git("https://korap.ids-mannheim.de/gerrit/IDS-Mannheim/idsThemeR", dependencies=TRUE)'
191 - R -e 'devtools::install_git("https://korap.ids-mannheim.de/gerrit/IDS-Mannheim/posterdown", dependencies=TRUE)'
Marc Kupietzce1aa0c2023-06-15 07:50:23 +0200192 - end_section install_r_packages
193
Marc Kupietze074d052025-06-20 13:50:10 +0200194 - start_section testing_html2pdf "Testing PDF export"
Marc Kupietzbbd089c2026-08-04 11:48:16 +0200195 - ./ci/html2pdf ci/html2pdf-smoke.html /tmp/html2pdf-smoke.pdf
196 - qpdf --check /tmp/html2pdf-smoke.pdf
Marc Kupietze074d052025-06-20 13:50:10 +0200197 - end_section testing_html2pdf
198
Marc Kupietzce1aa0c2023-06-15 07:50:23 +0200199 script:
Marc Kupietza39d0cc2024-05-31 12:45:45 +0200200 - start_section installing "Installing posterdown.ids"
Marc Kupietzce1aa0c2023-06-15 07:50:23 +0200201 - R -e 'devtools::install()'
202 - end_section installing
203 - start_section render "Generating demo artifacts"
Marc Kupietzf0eeb462024-05-31 16:13:55 +0200204 - R_CACHE_ROOTPATH=./cache R -e "require(rmarkdown); render('$SOURCE_FILE', output_format='posterdown.ids::posterdown_ids', output_dir='target')"
205 - export SVG=target/$(basename $SOURCE_FILE .Rmd).svg
206 - export HTML=target/$(basename $SOURCE_FILE .Rmd).html
207 - export PDF=target/$(basename $SOURCE_FILE .Rmd).pdf
208 - ./ci/html2pdf $HTML $PDF 1
Marc Kupietzc0ae3c22026-07-17 11:47:07 +0200209 # Variant for printing on fabric, where solid black bleeds out: replace all
210 # vector black by 15% grey (keeps QR codes scannable and text crisp).
Marc Kupietza01aee12026-08-04 10:33:17 +0200211 - export FABRIC_PDF=target/$(basename $SOURCE_FILE .Rmd)_fabric.pdf
212 - ./ci/pdf-lighten-black $PDF $FABRIC_PDF
213 # Add 10 mm of blank material on every side for mounting the fabric poster.
214 - pdfjam $FABRIC_PDF --papersize '{861mm,1209mm}' --noautoscale true --outfile target/$(basename $SOURCE_FILE .Rmd)_fabric-1cmborder.pdf
Marc Kupietzd13544d2026-07-17 11:04:45 +0200215 - gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -sPAPERSIZE=a1 -dFIXEDMEDIA -dPDFFitPage -sOutputFile=target/$(basename $SOURCE_FILE .Rmd)_a1.pdf $PDF
Marc Kupietzf0eeb462024-05-31 16:13:55 +0200216 - inkscape -b white --pdf-poppler -o $SVG $PDF || true
217 - scour -i $SVG -o target/skeleton_optimized.svg --enable-viewboxing --enable-id-stripping --shorten-ids --indent=none
Marc Kupietzce1aa0c2023-06-15 07:50:23 +0200218 - end_section render