16ea19ced8
Forgejo appears to immediately delete registry content that is overwritten. This means that we are forced to delete our previous workaround of making a temporary tag and use a new, more absurd workaround of making an entire temporary image that we basically only need to create to get its hash. However, on the plus side, the new workaround doesn't create garbage tags to begin with, which means that we don't have to deal with GitHub not implementing the standardized tag delete endpoint and instead only implementing a proprietary one. Upstream-Bug: https://github.com/containers/skopeo/issues/2354 Change-Id: I220e7ce9a17fd230c38882f12c009a166dcc9336
83 lines
3.2 KiB
Text
83 lines
3.2 KiB
Text
import json
|
|
import logging
|
|
from pathlib import Path
|
|
import tempfile
|
|
|
|
import requests
|
|
|
|
from .environment import DockerTarget, RelengEnvironment
|
|
from .version import VERSION, MAJOR
|
|
from . import gitutils
|
|
from .docker_assemble import Registry, OCIIndex, OCIIndexItem
|
|
from . import docker_assemble
|
|
|
|
log = logging.getLogger(__name__)
|
|
log.setLevel(logging.INFO)
|
|
|
|
def check_all_logins(env: RelengEnvironment):
|
|
for target in env.docker_targets:
|
|
check_login(target)
|
|
|
|
def check_login(target: DockerTarget):
|
|
log.info('Checking login for %s', target.registry_name)
|
|
skopeo login @(target.registry_name())
|
|
|
|
def upload_docker_images(target: DockerTarget, paths: list[Path]):
|
|
if not paths: return
|
|
|
|
sess = requests.Session()
|
|
sess.headers['User-Agent'] = 'lix-releng'
|
|
|
|
tag_names = [DockerTarget.resolve(tag, version=VERSION, major=MAJOR) for tag in target.tags]
|
|
|
|
# latest only gets tagged for the current release branch of Lix
|
|
if not gitutils.is_maintenance_branch('HEAD'):
|
|
tag_names.append('latest')
|
|
|
|
meta = {}
|
|
|
|
reg = docker_assemble.Registry(sess)
|
|
manifests = []
|
|
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
tmp = Path(tmp)
|
|
|
|
for path in paths:
|
|
digest_file = tmp / (path.name + '.digest')
|
|
tmp_image = tmp / 'tmp-image.tar.gz'
|
|
|
|
# insecure-policy: we don't have any signature policy, we are just uploading an image
|
|
#
|
|
# Absurd: we copy it into an OCI image first so we can get the hash
|
|
# we need to upload it untagged, because skopeo has no "don't tag
|
|
# this" option.
|
|
# The reason for this is that forgejo's container registry throws
|
|
# away old versions of tags immediately, so we cannot use a temp
|
|
# tag, and it *does* reduce confusion to not upload tags that
|
|
# should not be used.
|
|
#
|
|
# Workaround for: https://github.com/containers/skopeo/issues/2354
|
|
log.info('skopeo copy to temp oci-archive %s', tmp_image)
|
|
skopeo --insecure-policy copy --format oci --all --digestfile @(digest_file) docker-archive:@(path) oci-archive:@(tmp_image)
|
|
|
|
inspection = json.loads($(skopeo inspect oci-archive:@(tmp_image)))
|
|
|
|
docker_arch = inspection['Architecture']
|
|
docker_os = inspection['Os']
|
|
meta = inspection['Labels']
|
|
|
|
log.info('Pushing image %s for %s to %s', path, docker_arch, target.registry_path)
|
|
|
|
digest = digest_file.read_text().strip()
|
|
skopeo --insecure-policy copy --preserve-digests --all oci-archive:@(tmp_image) f'docker://{target.registry_path}@{digest}'
|
|
|
|
# skopeo doesn't give us the manifest size directly, so we just ask the registry
|
|
metadata = reg.image_info(target.registry_path, digest)
|
|
|
|
manifests.append(OCIIndexItem(metadata=metadata, architecture=docker_arch, os=docker_os))
|
|
|
|
log.info('Pushed images to %r, building a bigger and more menacing manifest from %r with metadata %r', target, manifests, meta)
|
|
# send the multiarch manifest to each tag
|
|
index = OCIIndex(manifests=manifests, annotations=meta)
|
|
for tag in tag_names:
|
|
reg.upload_index(target.registry_path, tag, index)
|