Skip to content

Instantly share code, notes, and snippets.

@tongpu
Last active August 8, 2025 13:14
Show Gist options
  • Save tongpu/eb30b413025b414a84f2f04d45264fc5 to your computer and use it in GitHub Desktop.
Save tongpu/eb30b413025b414a84f2f04d45264fc5 to your computer and use it in GitHub Desktop.
Migrate GitHub Container registry images from one organisation to another
#!/usr/bin/env python3
import requests
import podman
import io
def get_all_versions(
package_name: str,
org: str,
) -> list[str]:
session = requests.Session()
tagged_versions = []
current_url = f"https://api.github.com/orgs/{org}/packages/container/{package_name}/versions?per_page=100"
# Loop over all pages in the API
while True:
print(f"Fetching versions from {current_url}")
versions = session.get(current_url)
for version in versions.json():
if version["metadata"]["container"]["tags"] != []:
tagged_versions.extend(version["metadata"]["container"]["tags"])
# Get the link to the next page from the response
next_link = versions.links.get("next")
if next_link:
current_url = next_link["url"]
else:
# No more pages to fetch, break the loop
break
return tagged_versions
def podman_rebuild_image(
package_name: str, tag: str, source_org: str, dest_org: str
) -> None:
# Enforce lowercase for container repository names
source_container_repo = f"ghcr.io/{source_org}/{package_name}".lower()
dest_container_repo = f"ghcr.io/{dest_org}/{package_name}".lower()
with podman.PodmanClient() as client:
print(f"Pulling {source_container_repo}:{tag}")
source_image = client.images.pull(source_container_repo, tag)
dest_labels = source_image.labels
dest_labels["org.opencontainers.image.url"] = (
f"https://github.com/{dest_org}/{package_name}"
)
dest_labels["org.opencontainers.image.source"] = (
f"https://github.com/{dest_org}/{package_name}"
)
print(f"Building {dest_container_repo}:{tag}")
client.images.build(
fileobj=io.StringIO(
f"FROM ghcr.io/{source_org.lower()}/{package_name}:{tag}"
),
tag=f"{dest_container_repo}:{tag}",
labels=dest_labels,
)
print(f"Pushing {dest_container_repo}:{tag}")
client.images.push(dest_container_repo, tag)
return
if __name__ == "__main__":
source_org = "SourceOrganization"
dest_org = "DestinationOrganization"
package_name = "example-package"
package_tags = get_all_versions(package_name, source_org)
for tag in package_tags:
podman_rebuild_image(package_name, tag, source_org, dest_org)
podman~=5.5
requests~=2.32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment