Dockerfiles: reuse build arguments
- [x] I have read the contributing guideline and understand that I have made the correct modifications
Description:
This PR puts all image configuration and convenience variables at the top-level of the respective Dockerfile (before any stage) as ARG <key>[=<value>] instructions. Top-level ARGs can be imported by following stages via ARG <key> (i.e., without setting a value).
See below for further details.
Benefits of this PR and context:
Putting all "living" build arguments at the top-level makes it more convenient and less error prone to copy/paste and typos when changing values in the future, as those can now be set in one single place only and are imported into all stages which require them.
Take the current master branch for example. This line is defined in the stage rootfs-stage:
ENV ROOTFS=/root-out
However, a couple lines later, /root-out is explicitly stated again:
sed -i -e 's/^root::/root:!:/' /root-out/etc/shadow
This PR just defines ROOTFS at the top level and uses it throughout the whole file.
How Has This Been Tested?
I'll just paste this log of my terminal inputs/outputs here:
building the image from master branch
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
$ git show --shortstat
commit d9e9c8a664eb5fe2023d2626ddf1e062461f824e (HEAD -> master, origin/master, origin/HEAD)
Author: LinuxServer-CI <[email protected]>
Date: Sat Mar 29 13:33:30 2025 +0000
Bot Updating Package Versions
1 file changed, 1 insertion(+), 1 deletion(-)
$ docker build --build-arg VERSION=master --build-arg BUILD_DATE=20220321 -t alpine-base:master .
[+] Building 5.4s (33/33) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 3.41kB 0.0s
=> resolve image config for docker-image://docker.io/docker/dockerfile:1 1.0s
=> CACHED docker-image://docker.io/docker/dockerfile:1@sha256:4c68376a702446fc3c79af22de146a148bc3367e73c25a5803d453b6b3f722fb 0.0s
=> [internal] load metadata for docker.io/library/alpine:3.20 0.5s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 107B 0.0s
=> [stage-1 5/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/with-contenv.v1 /usr/bin/with-contenv 0.3s
=> [rootfs-stage 1/11] FROM docker.io/library/alpine:3.20@sha256:de4fe7064d8f98419ea6b49190df1abbf43450c1702eeb864fe9ced453c1cc5f 0.0s
=> [stage-1 4/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/lsiown.v1 /usr/bin/lsiown 0.3s
=> [rootfs-stage 8/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-symlinks-noarch.tar.xz /tmp 0.9s
=> [internal] load build context 0.1s
=> => transferring context: 6.69kB 0.1s
=> [stage-1 3/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/package-install.v1 /etc/s6-overlay/s6-rc. 0.3s
=> [stage-1 2/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/docker-mods.v3 /docker-mods 0.3s
=> [rootfs-stage 6/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-x86_64.tar.xz /tmp 0.9s
=> [rootfs-stage 10/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-symlinks-arch.tar.xz /tmp 0.9s
=> [rootfs-stage 4/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-noarch.tar.xz /tmp 0.9s
=> CACHED [rootfs-stage 2/11] RUN apk add --no-cache bash xz 0.0s
=> CACHED [rootfs-stage 3/11] RUN mkdir -p "/root-out/etc/apk" && { echo "http://dl-cdn.alpinelinux.org/alpine/v3.21/main"; echo "h 0.0s
=> CACHED [rootfs-stage 4/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-noarch.tar.xz /tmp 0.0s
=> CACHED [rootfs-stage 5/11] RUN tar -C /root-out -Jxpf /tmp/s6-overlay-noarch.tar.xz 0.0s
=> CACHED [rootfs-stage 6/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-x86_64.tar.xz /tmp 0.0s
=> CACHED [rootfs-stage 7/11] RUN tar -C /root-out -Jxpf /tmp/s6-overlay-x86_64.tar.xz 0.0s
=> CACHED [rootfs-stage 8/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-symlinks-noarch.tar.xz /t 0.0s
=> CACHED [rootfs-stage 9/11] RUN tar -C /root-out -Jxpf /tmp/s6-overlay-symlinks-noarch.tar.xz && unlink /root-out/usr/bin/with-contenv 0.0s
=> CACHED [rootfs-stage 10/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-symlinks-arch.tar.xz /tmp 0.0s
=> CACHED [rootfs-stage 11/11] RUN tar -C /root-out -Jxpf /tmp/s6-overlay-symlinks-arch.tar.xz 0.0s
=> CACHED [stage-1 1/7] COPY --from=rootfs-stage /root-out/ / 0.0s
=> CACHED [stage-1 2/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/docker-mods.v3 /docker-mods 0.0s
=> CACHED [stage-1 3/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/package-install.v1 /etc/s6-overlay 0.0s
=> CACHED [stage-1 4/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/lsiown.v1 /usr/bin/lsiown 0.0s
=> CACHED [stage-1 5/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/with-contenv.v1 /usr/bin/with-cont 0.0s
=> [stage-1 6/7] RUN echo "**** install runtime packages ****" && apk add --no-cache alpine-release bash ca-certificates cat 2.3s
=> [stage-1 7/7] COPY root/ / 0.1s
=> exporting to image 0.2s
=> => exporting layers 0.2s
=> => writing image sha256:9edc053f941cd6e829c40f17b413be9e959b433d1f457eef12014c38981ae4b1 0.0s
=> => naming to docker.io/library/alpine-base:master
$ docker inspect alpine-base:master | jq '.[0].Config'
{
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/lsiopy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"PS1=$(whoami)@$(hostname):$(pwd)\\$ ",
"HOME=/root",
"TERM=xterm",
"S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0",
"S6_VERBOSITY=1",
"S6_STAGE2_HOOK=/docker-mods",
"VIRTUAL_ENV=/lsiopy"
],
"Cmd": null,
"Image": "",
"Volumes": null,
"WorkingDir": "/",
"Entrypoint": [
"/init"
],
"OnBuild": null,
"Labels": {
"build_version": "Linuxserver.io version:- master Build-date:- 20220321",
"maintainer": "TheLamer"
}
}
building the image from branch dockerfiles/reuse-build-arguments
$ git checkout dockerfiles/reuse-build-arguments
Switched to branch 'dockerfiles/reuse-build-arguments'
$ git status
On branch dockerfiles/reuse-build-arguments
nothing to commit, working tree clean
$ git show --shortstat
commit e7612f735caa8808d4295b6696146f18dd0df83b (HEAD -> dockerfiles/reuse-build-arguments, origin/dockerfiles/reuse-build-arguments)
Author: Timo Reichl <[email protected]>
Date: Sun Mar 30 19:03:58 2025 +0200
Dockerfile.aarch64: Reuse build arguments
Signed-off-by: Timo Reichl <[email protected]>
1 file changed, 127 insertions(+), 51 deletions(-)
$ docker build --build-arg VERSION="reuse-build-arguments" --build-arg BUILD_DATE=20220321 -t alpine-base:test .
[+] Building 3.7s (33/33) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 5.17kB 0.0s
=> resolve image config for docker-image://docker.io/docker/dockerfile:1 0.2s
=> CACHED docker-image://docker.io/docker/dockerfile:1@sha256:4c68376a702446fc3c79af22de146a148bc3367e73c25a5803d453b6b3f722fb 0.0s
=> [internal] load metadata for docker.io/library/alpine:3.20 0.1s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 107B 0.0s
=> [rootfs-stage 1/11] FROM docker.io/library/alpine:3.20@sha256:de4fe7064d8f98419ea6b49190df1abbf43450c1702eeb864fe9ced453c1cc5f 0.0s
=> [rootfs-stage 6/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-x86_64.tar.xz /tmp 0.5s
=> [internal] load build context 0.1s
=> => transferring context: 6.69kB 0.1s
=> [stage-1 5/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/refs/heads/mod-scripts/with-contenv.v1 /usr/bin/with- 0.1s
=> [stage-1 4/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/refs/heads/mod-scripts/lsiown.v1 /usr/bin/lsiown 0.0s
=> [rootfs-stage 4/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-noarch.tar.xz /tmp 0.4s
=> [stage-1 3/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/refs/heads/mod-scripts/package-install.v1 /etc/s6-ove 0.0s
=> [stage-1 2/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/refs/heads/mod-scripts/docker-mods.v3 /docker-mods 0.0s
=> [rootfs-stage 10/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-symlinks-arch.tar.xz /tmp 0.5s
=> [rootfs-stage 8/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-symlinks-noarch.tar.xz /tmp 0.5s
=> CACHED [rootfs-stage 2/11] RUN apk add --no-cache bash xz 0.0s
=> CACHED [rootfs-stage 3/11] RUN mkdir -p "/root-out/etc/apk" && { echo "http://dl-cdn.alpinelinux.org/alpine/v3.21/main"; echo "h 0.0s
=> CACHED [rootfs-stage 4/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-noarch.tar.xz /tmp 0.0s
=> CACHED [rootfs-stage 5/11] RUN tar -C /root-out -Jxpf /tmp/s6-overlay-noarch.tar.xz 0.0s
=> CACHED [rootfs-stage 6/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-x86_64.tar.xz /tmp 0.0s
=> CACHED [rootfs-stage 7/11] RUN tar -C /root-out -Jxpf /tmp/s6-overlay-x86_64.tar.xz 0.0s
=> CACHED [rootfs-stage 8/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-symlinks-noarch.tar.xz /t 0.0s
=> CACHED [rootfs-stage 9/11] RUN tar -C /root-out -Jxpf /tmp/s6-overlay-symlinks-noarch.tar.xz && unlink /root-out/usr/bin/with-contenv 0.0s
=> CACHED [rootfs-stage 10/11] ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-symlinks-arch.tar.xz /tmp 0.0s
=> CACHED [rootfs-stage 11/11] RUN tar -C /root-out -Jxpf /tmp/s6-overlay-symlinks-arch.tar.xz 0.0s
=> CACHED [stage-1 1/7] COPY --from=rootfs-stage /root-out / 0.0s
=> CACHED [stage-1 2/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/refs/heads/mod-scripts/docker-mods.v3 /docker- 0.0s
=> CACHED [stage-1 3/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/refs/heads/mod-scripts/package-install.v1 /etc 0.0s
=> CACHED [stage-1 4/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/refs/heads/mod-scripts/lsiown.v1 /usr/bin/lsio 0.0s
=> CACHED [stage-1 5/7] ADD --chmod=755 https://raw.githubusercontent.com/linuxserver/docker-mods/refs/heads/mod-scripts/with-contenv.v1 /usr/bi 0.0s
=> [stage-1 6/7] RUN echo "**** install runtime packages ****" && apk add --no-cache alpine-release bash ca-certificates cat 2.2s
=> [stage-1 7/7] COPY root/ / 0.2s
=> exporting to image 0.2s
=> => exporting layers 0.2s
=> => writing image sha256:87c3f90064e99c1ef557e69bdcd0a964bd03eeb039b432a70971fb77e96e9052 0.0s
=> => naming to docker.io/library/alpine-base:test 0.0s
$ docker inspect alpine-base:test | jq '.[0].Config'
{
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/lsiopy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"PS1=$(whoami)@$(hostname):$(pwd)\\$ ",
"HOME=/root",
"TERM=xterm",
"S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0",
"S6_VERBOSITY=1",
"S6_STAGE2_HOOK=/docker-mods",
"VIRTUAL_ENV=/lsiopy"
],
"Cmd": null,
"Image": "",
"Volumes": null,
"WorkingDir": "/",
"Entrypoint": [
"/init"
],
"OnBuild": null,
"Labels": {
"build_version": "Linuxserver.io version:- reuse-build-arguments Build-date:- 20220321",
"maintainer": "TheLamer"
}
}
running lscr.io/linuxserver/jenkins-builder:latest
$ docker pull lscr.io/linuxserver/jenkins-builder:latest && docker run --rm -v $(pwd):/tmp -e PUID=$(id -u) -e PGID=$(id -g) > /tmp/jenkins-builder.log lscr.io/linuxserver/jenkins-builder:latest && rm -rf .jenkins-external
latest: Pulling from linuxserver/jenkins-builder
Digest: sha256:7524be744450c9a07938e018448bafa89a78aa00a5ce331db409a1a26976f46b
Status: Image is up to date for lscr.io/linuxserver/jenkins-builder:latest
lscr.io/linuxserver/jenkins-builder:latest
$ cat /tmp/jenkins-builder.log
Linuxserver.io version: ecf81715-ls242
Build-date: 2025-03-27T12:58:47+00:00
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Set container_name] ******************************************************
ok: [localhost]
TASK [Set github_branch] *******************************************************
ok: [localhost]
TASK [Set UID] *****************************************************************
ok: [localhost]
TASK [Set GID] *****************************************************************
ok: [localhost]
TASK [Set noter] ***************************************************************
ok: [localhost]
TASK [Include var files for this project] **************************************
ok: [localhost] => (item=jenkins-vars.yml)
ok: [localhost] => (item=readme-vars.yml)
TASK [Add deprecation in S6] ***************************************************
skipping: [localhost]
TASK [Setup .github meta directory] ********************************************
included: github for localhost
TASK [github : Create .github directories] *************************************
ok: [localhost] => (item=.github/ISSUE_TEMPLATE)
ok: [localhost] => (item=.github/workflows)
TASK [github : Populate Github workflows] **************************************
changed: [localhost] => (item=call_issue_pr_tracker.yml)
changed: [localhost] => (item=call_issues_cron.yml)
ok: [localhost] => (item=external_trigger_scheduler.yml)
ok: [localhost] => (item=external_trigger.yml)
changed: [localhost] => (item=greetings.yml)
ok: [localhost] => (item=package_trigger_scheduler.yml)
changed: [localhost] => (item=permissions.yml)
TASK [github : Populate conditional Github workflows] **************************
ok: [localhost] => (item={'file': 'package_trigger_scheduler.yml', 'when': 'custom_package_trigger != true'})
ok: [localhost] => (item={'file': 'external_trigger_scheduler.yml', 'when': 'custom_external_trigger != true'})
ok: [localhost] => (item={'file': 'external_trigger.yml', 'when': 'custom_external_trigger != true'})
TASK [github : Populate Github issue templates] ********************************
changed: [localhost] => (item=issue.bug.yml)
changed: [localhost] => (item=config.yml)
changed: [localhost] => (item=issue.feature.yml)
TASK [github : Populate Github metadata] ***************************************
changed: [localhost] => (item=CONTRIBUTING.md)
changed: [localhost] => (item=FUNDING.yml)
ok: [localhost] => (item=PULL_REQUEST_TEMPLATE.md)
TASK [Generate documentation] **************************************************
included: documentation for localhost
TASK [documentation : Create Jenkins external directories] *********************
changed: [localhost]
TASK [documentation : Template Unraid template] ********************************
skipping: [localhost]
TASK [documentation : Template MkDocs page] ************************************
changed: [localhost]
TASK [documentation : Template lite README] ************************************
changed: [localhost]
TASK [documentation : Template README] *****************************************
ok: [localhost]
TASK [Generate Repository] *****************************************************
included: repository for localhost
TASK [repository : Create Root directory for donation] *************************
skipping: [localhost]
TASK [repository : Populate donation file] *************************************
skipping: [localhost]
TASK [repository : Populate Repository files] **********************************
changed: [localhost] => (item=.editorconfig)
ok: [localhost] => (item=Jenkinsfile)
ok: [localhost] => (item=LICENSE)
PLAY RECAP *********************************************************************
localhost : ok=20 changed=7 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
Rinse and repeat for Dockerfile.aarch64.
Testing environment
$ id
uid=1000(user) gid=1000(user) groups=1000(user),27(sudo),995(docker)
$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
$ uname -a
Linux docker-dev 6.12.12-zabbly+ #debian12 SMP PREEMPT_DYNAMIC Sun Feb 2 11:29:26 UTC 2025 x86_64 GNU/Linux
$ docker version
Client: Docker Engine - Community
Version: 27.5.1
API version: 1.47
Go version: go1.22.11
Git commit: 9f9e405
Built: Wed Jan 22 13:41:17 2025
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 27.5.1
API version: 1.47 (minimum version 1.24)
Go version: go1.22.11
Git commit: 4c9b3b0
Built: Wed Jan 22 13:41:17 2025
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.7.25
GitCommit: bcc810d6b9066471b0b6fa75f557a15a1cbf31bb
runc:
Version: 1.2.4
GitCommit: v1.2.4-0-g6c52b3f
docker-init:
Version: 0.19.0
GitCommit: de40ad0
$ docker info
Client: Docker Engine - Community
Version: 27.5.1
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.20.0
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.32.4
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 12
Server Version: 27.5.1
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: bcc810d6b9066471b0b6fa75f557a15a1cbf31bb
runc version: v1.2.4-0-g6c52b3f
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.12.12-zabbly+
Operating System: Debian GNU/Linux 12 (bookworm)
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 3.804GiB
Name: docker-dev
ID: d564d82b-4574-4beb-a553-dfd5bffbe41b
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://docker-hub.infra.incus.thetre.dev/
Live Restore Enabled: false
Source / References:
N/A
I am a bot, here are the test results for this PR: https://ci-tests.linuxserver.io/lspipepr/alpine/3.21-4080e67e-pkg-4080e67e-dev-e7612f735caa8808d4295b6696146f18dd0df83b-pr-257/index.html https://ci-tests.linuxserver.io/lspipepr/alpine/3.21-4080e67e-pkg-4080e67e-dev-e7612f735caa8808d4295b6696146f18dd0df83b-pr-257/shellcheck-result.xml
| Tag | Passed |
|---|---|
| amd64-3.21-4080e67e-pkg-4080e67e-dev-e7612f735caa8808d4295b6696146f18dd0df83b-pr-257 | ✅ |
| arm64v8-3.21-4080e67e-pkg-4080e67e-dev-e7612f735caa8808d4295b6696146f18dd0df83b-pr-257 | ✅ |
I'm not rejecting or ignoring this but it's not something that can just be applied to a single branch of a single base image, it would need to be replicated across the board and that takes a lot of thought and planning.
I'll probably look at the options for implementing some or all of this PR as part of the Alpine 3.22 base image branch when that's released in the next month or so.
@thespad yeah sorry about bluntly posting this PR without a related issue first. I didn't know how to start this kind of conversation the best way.
Either way I thought about the other base images as well. I could provide PRs for those as soon as the changes of this specific PR are deemed mergeable. What do you think?
PRs for other branches and bases will likely come when there's some other reason to touch them as there's not a huge benefit to retrofitting changes like this to older images, but I'll have a better sense of what's needed once 3.22 is up and running.
I am a bot, here are the test results for this PR: https://ci-tests.linuxserver.io/lspipepr/alpine/3.21-532ba5e0-pkg-532ba5e0-dev-8aa504bcc419f60fa96caac0f253c8c13f335b59-pr-257/index.html https://ci-tests.linuxserver.io/lspipepr/alpine/3.21-532ba5e0-pkg-532ba5e0-dev-8aa504bcc419f60fa96caac0f253c8c13f335b59-pr-257/shellcheck-result.xml
| Tag | Passed |
|---|---|
| amd64-3.21-532ba5e0-pkg-532ba5e0-dev-8aa504bcc419f60fa96caac0f253c8c13f335b59-pr-257 | ✅ |
| arm64v8-3.21-532ba5e0-pkg-532ba5e0-dev-8aa504bcc419f60fa96caac0f253c8c13f335b59-pr-257 | ✅ |
