Skip to content

Commit e782d84

Browse files
committed
generic-packs: support oci:// references via install-oci-pack
Allow GENERIC_PACKS entries to point at OCI modpack artifacts in a container registry using an oci:// reference (tag or @sha256: digest). Such entries are pulled with mc-image-helper install-oci-pack and the resulting layer paths are appended to packFiles in manifest order, so the existing extract, disable-mods, manifest-diff, and checksum pipeline applies unchanged. OCI, URL, and local entries can be mixed in one list and apply in declared order. Layers are cached under /data/packs/oci by digest, so a base layer shared between packs is fetched only once. Registry auth can be supplied with GENERIC_PACKS_OCI_AUTH_FILE; artifact and layer media types are validated by the helper.
1 parent 292b2f7 commit e782d84

7 files changed

Lines changed: 84 additions & 1 deletion

File tree

docs/mods-and-plugins/index.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,26 @@ GENERIC_PACKS_SUFFIX=.zip
138138

139139
would expand to `https://cdn.example.org/configs-v9.0.1.zip,https://cdn.example.org/mods-v4.3.6.zip`.
140140

141+
### Generic packs from an OCI registry
142+
143+
An entry can also reference a pack stored as an [OCI](https://opencontainers.org/) artifact in a container registry by prefixing it with `oci://`. The reference may use a tag or an immutable `@sha256:` digest:
144+
145+
```
146+
GENERIC_PACKS=oci://ghcr.io/chipwolf/oci-modpack-demo/tech:latest,oci://ghcr.io/chipwolf/oci-modpack-demo/magic:latest
147+
```
148+
149+
OCI, URL, and local-path entries can be mixed in the same list and are applied in the order given. Each artifact's layers are pulled into a content-addressed cache under `/data/packs/oci`, so a digest already on disk (for example a base layer shared between packs) is not downloaded again. `GENERIC_PACKS_PREFIX`/`GENERIC_PACKS_SUFFIX`, `GENERIC_PACKS_DISABLE_MODS`, and the update/checksum behaviour below all apply to OCI entries exactly as they do to URLs.
150+
151+
The artifact must be a Minecraft modpack artifact (artifact type `application/vnd.itzg.minecraft.modpack.v1+json` with `…modpack.layer.v1.tar+gzip` layers); any other reference is rejected before its contents touch `/data`. Validation and registry authentication are handled by `mc-image-helper`.
152+
153+
For a private registry, point `GENERIC_PACKS_OCI_AUTH_FILE` at a registry login file (the `auth.json`/`config.json` produced by `docker login`, `podman login`, etc.):
154+
155+
```
156+
GENERIC_PACKS_OCI_AUTH_FILE=/run/secrets/registry-auth.json
157+
```
158+
159+
When it is unset, a credentials file at `~/.config/containers/auth.json` or `~/.docker/config.json` is used if present, otherwise the pull is anonymous.
160+
141161
If applying large generic packs, the update can be time-consuming. To skip the update set `SKIP_GENERIC_PACK_UPDATE_CHECK` to "true". Conversely, the generic pack(s) can be forced to be applied by setting `FORCE_GENERIC_PACK_UPDATE` to "true".
142162

143163
The most time-consuming portion of the generic pack update is generating and comparing the SHA1 checksum. To skip the checksum generation, set `SKIP_GENERIC_PACK_CHECKSUM` to "true".

scripts/start-setupModpack

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,38 @@ function handleGenericPacks() {
170170
packFiles=()
171171
for packEntry in "${packs[@]}"; do
172172
pack="${GENERIC_PACKS_PREFIX}${packEntry}${GENERIC_PACKS_SUFFIX}"
173-
if isURL "${pack}"; then
173+
if isOCIRef "${pack}"; then
174+
# All OCI refs share one staging dir so layers common to multiple
175+
# sibling artifacts (the point of layered distribution) are pulled
176+
# exactly once across all of GENERIC_PACKS.
177+
mkdir -p /data/packs/oci /data/.tmp
178+
log "Pulling OCI generic pack from $pack"
179+
# A list file is used rather than stdout because mc-image-helper INFO
180+
# logs share that stream; it holds one absolute layer path per line in
181+
# apply order.
182+
layerListFile=$(mktemp -p /data/.tmp)
183+
ociArgs=(install-oci-pack
184+
--ref "$pack"
185+
--output-directory /data/packs/oci
186+
--filename-strategy digest
187+
--layer-list-file "$layerListFile")
188+
if [[ "${GENERIC_PACKS_OCI_AUTH_FILE:-}" ]]; then
189+
ociArgs+=(--auth-file "${GENERIC_PACKS_OCI_AUTH_FILE}")
190+
fi
191+
if ! mc-image-helper "${ociArgs[@]}"; then
192+
logError "Failed to pull OCI generic pack $pack"
193+
logError "(OCI generic packs require mc-image-helper with install-oci-pack support)"
194+
rm -f "$layerListFile"
195+
exit 2
196+
fi
197+
mapfile -t ociLayers < "$layerListFile"
198+
rm -f "$layerListFile"
199+
if [ ${#ociLayers[@]} -eq 0 ]; then
200+
logError "OCI generic pack $pack resolved to zero layers"
201+
exit 2
202+
fi
203+
packFiles+=("${ociLayers[@]}")
204+
elif isURL "${pack}"; then
174205
mkdir -p /data/packs
175206
log "Downloading generic pack from $pack"
176207
if ! outfile=$(get -o /data/packs --output-filename --skip-up-to-date "$pack"); then

scripts/start-utils

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ function isURL() {
173173
[[ $value =~ ^(https?|ftp):// ]]
174174
}
175175

176+
function isOCIRef() {
177+
local value=$1
178+
179+
[[ $value =~ ^oci:// ]]
180+
}
181+
176182
function isValidFileURL() {
177183
suffix=${1:?Missing required suffix arg}
178184
url=${2:?Missing required url arg}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
services:
2+
mc:
3+
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
4+
environment:
5+
EULA: "true"
6+
SETUP_ONLY: "true"
7+
# two OCI packs that share a common base layer; the shared blob is
8+
# pulled into /data/packs/oci once and reused for the second pack
9+
GENERIC_PACKS: oci://ghcr.io/chipwolf/oci-modpack-demo/tech:latest,oci://ghcr.io/chipwolf/oci-modpack-demo/magic:latest
10+
LOG_TIMESTAMP: "true"
11+
# the following are only used to speed up test execution
12+
TYPE: CUSTOM
13+
CUSTOM_SERVER: /servers/fake.jar
14+
VERSION: 1.18.1
15+
DEBUG: "true"
16+
volumes:
17+
- ./data:/data
18+
- ./fake.jar:/servers/fake.jar

tests/setuponlytests/generic-packs-oci/fake.jar

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[[ $EXTENDED_TESTS ]] || exit 1
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
set -e
2+
# OCI layers were cached
3+
[ -d /data/packs/oci ]
4+
compgen -G "/data/packs/oci/sha256:*" > /dev/null
5+
# pack content was extracted and applied to /data
6+
[ -d /data/mods ]
7+
compgen -G "/data/mods/*" > /dev/null

0 commit comments

Comments
 (0)