fix: get all imported challenges building and running
Root causes found by prebuilding every challenge image in parallel:
- fjb: ghcr.io base is not anonymously pullable here -> official httpd:2.4.
pnpm 12 (via corepack on node:20) fails the install with
ERR_PNPM_IGNORED_BUILDS unless build scripts are approved; neither
onlyBuiltDependencies in pnpm-workspace.yaml nor --no-ignore-scripts
suppresses it. The working sequence is:
pnpm install --ignore-scripts && pnpm approve-builds --all && pnpm rebuild
- xl + kode-viewer: node:20-slim-bookworm is not a real tag -> node:20-bookworm-slim.
- burvesigner: python-dev no longer exists in bookworm -> dropped (python3-dev
was already there and the source has no py2 syntax).
- burvesigner/hirnfick/s3: apt update and install were separate RUN layers;
with the bundled apt-insecure.conf the second invocation re-resolved against
the EOL bullseye-security mirror and 404'd every package. Merged into one
'update && install' layer (fix_apt_layers.py, idempotent).
- consolidate_images.sh: teams used to build a private image per team
(team1-x ... team4-x) because no shared image existed. Since the password is
applied at runtime via chpasswd, one shared services-<name> build is enough;
this reclaims ~1.5 GB, which matters on a 79 GB disk.
- reconcile_team_state(): a challenge enabled while a team was down left
state.json without ports/flag/password, so the next compose render died with
KeyError. Now both the API and the CLI tools reconcile first.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Merge a Dockerfile's split `apt-get update` + `apt-get install` into one RUN.
|
||||
|
||||
Why: several imported challenge Dockerfiles run
|
||||
|
||||
RUN apt-get -o Acquire::AllowInsecureRepositories=true update
|
||||
RUN apt-get -y --allow-unauthenticated install -y ...
|
||||
|
||||
as two separate layers. The bundled apt-insecure.conf enables insecure/downgrade
|
||||
repositories, and a second apt invocation in a later layer re-resolves against
|
||||
whatever index the first one left behind — which on the EOL bullseye-security
|
||||
mirror returns 404 for every package:
|
||||
|
||||
Err:1 http://deb.debian.org/debian-security bullseye-security/main amd64 libsystemd0
|
||||
404 Not Found
|
||||
|
||||
Merging them into a single `update && install` layer (the pattern the working
|
||||
gemastik18 challenges use) makes apt resolve once, from a fresh index.
|
||||
|
||||
Idempotent: a Dockerfile that already has the combined form is left untouched.
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SERVICES = Path("/opt/gemastik18-final/services")
|
||||
|
||||
UPDATE_RE = re.compile(
|
||||
r"^RUN\s+apt-get\s+(?P<opts>(?:-o\s+\S+\s+)*)update\s*$"
|
||||
)
|
||||
INSTALL_RE = re.compile(r"^RUN\s+(?P<rest>apt-get\s+.*\binstall\b.*)$")
|
||||
|
||||
|
||||
def fix(text: str) -> tuple[str, bool]:
|
||||
lines = text.splitlines()
|
||||
out: list[str] = []
|
||||
i = 0
|
||||
changed = False
|
||||
while i < len(lines):
|
||||
m = UPDATE_RE.match(lines[i])
|
||||
if not m:
|
||||
out.append(lines[i])
|
||||
i += 1
|
||||
continue
|
||||
# look ahead: is the very next non-empty line an install?
|
||||
j = i + 1
|
||||
while j < len(lines) and not lines[j].strip():
|
||||
j += 1
|
||||
if j < len(lines):
|
||||
mi = INSTALL_RE.match(lines[j])
|
||||
if mi:
|
||||
out.append(f"RUN apt-get {m.group('opts')}update && \\")
|
||||
out.append(f" {mi.group('rest')}")
|
||||
changed = True
|
||||
i = j + 1
|
||||
continue
|
||||
out.append(lines[i])
|
||||
i += 1
|
||||
return "\n".join(out) + ("\n" if text.endswith("\n") else ""), changed
|
||||
|
||||
|
||||
def main(argv):
|
||||
names = argv[1:] or [p.name for p in sorted(SERVICES.iterdir())
|
||||
if p.is_dir() and (p / "Dockerfile").exists()]
|
||||
changed = []
|
||||
for name in names:
|
||||
p = SERVICES / name / "Dockerfile"
|
||||
if not p.exists():
|
||||
continue
|
||||
text = p.read_text()
|
||||
new, did = fix(text)
|
||||
if did:
|
||||
p.write_text(new)
|
||||
changed.append(name)
|
||||
print(f"{name}: merged apt update+install into one RUN")
|
||||
print("rewritten:", ", ".join(changed) if changed else "(none)")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main(sys.argv))
|
||||
Reference in New Issue
Block a user