Skip to main content

Overview

This page provides practical examples demonstrating common workflows with the python-copr client library.

Setup and Initialization

Basic Client Setup

from copr.v3 import Client

# Load from default location (~/.config/copr)
client = Client.create_from_config_file()

Configuration File Format

Create ~/.config/copr with your API credentials:
[copr-cli]
login = abc123def456
username = myusername
token = xyz789uvw012
copr_url = https://copr.fedorainfracloud.org
Obtain your API credentials from https://copr.fedoraproject.org/api after logging in.

Project Management

Creating a Project

from copr.v3 import Client

client = Client.create_from_config_file()

# Create a new project with multiple chroots
project = client.project_proxy.add(
    ownername="myusername",
    projectname="my-awesome-project",
    chroots=[
        "fedora-39-x86_64",
        "fedora-40-x86_64",
        "epel-9-x86_64",
    ],
    description="My awesome software packages",
    instructions="dnf copr enable myusername/my-awesome-project",
    homepage="https://github.com/myusername/myproject",
    contact="[email protected]",
    enable_net=False,  # Disable network access during builds
    auto_prune=True,  # Automatically delete old builds
)

print(f"Project created: {project.name}")
print(f"Full name: {project.full_name}")

Getting Project Information

from copr.v3 import Client

client = Client.create_from_config_file()

# Get a specific project
project = client.project_proxy.get("@copr", "copr-dev")

print(f"Project: {project.name}")
print(f"Owner: {project.ownername}")
print(f"Description: {project.description}")
print(f"Chroots: {', '.join(project.chroot_repos.keys())}")

Listing Projects

from copr.v3 import Client

client = Client.create_from_config_file()

# List all projects for a user
projects = client.project_proxy.get_list(ownername="myusername")

for project in projects:
    print(f"- {project.name}: {project.description}")

Searching Projects

from copr.v3 import Client

client = Client.create_from_config_file()

# Search for projects containing "python"
results = client.project_proxy.search("python")

for project in results:
    print(f"{project.full_name} - {project.description}")

Editing a Project

from copr.v3 import Client

client = Client.create_from_config_file()

# Update project settings
project = client.project_proxy.edit(
    ownername="myusername",
    projectname="my-awesome-project",
    description="Updated description for my project",
    chroots=["fedora-39-x86_64", "fedora-40-x86_64", "fedora-41-x86_64"],
    enable_net=True,  # Now allow network access
)

print(f"Project updated: {project.name}")

Forking a Project

from copr.v3 import Client

client = Client.create_from_config_file()

# Fork another user's project
forked = client.project_proxy.fork(
    ownername="otheruser",
    projectname="their-project",
    dstownername="myusername",
    dstprojectname="my-fork",
)

print(f"Forked to: {forked.full_name}")

Deleting a Project

from copr.v3 import Client

client = Client.create_from_config_file()

# Delete a project
result = client.project_proxy.delete(
    ownername="myusername",
    projectname="old-project",
)

print("Project deleted successfully")

Building Packages

Build from URL

from copr.v3 import Client

client = Client.create_from_config_file()

# Submit a build from a SRPM URL
build = client.build_proxy.create_from_url(
    ownername="myusername",
    projectname="my-awesome-project",
    url="https://example.com/packages/mypackage-1.0-1.src.rpm",
)

print(f"Build submitted: ID {build.id}")
print(f"State: {build.state}")

Build from Local File

from copr.v3 import Client

client = Client.create_from_config_file()

# Upload and build a local SRPM
build = client.build_proxy.create_from_file(
    ownername="myusername",
    projectname="my-awesome-project",
    path="/path/to/mypackage-1.0-1.src.rpm",
)

print(f"Build ID: {build.id}")
print(f"Package: {build.source_package.name}")

Build from Git Repository

from copr.v3 import Client

client = Client.create_from_config_file()

# Build from a Git repository
build = client.build_proxy.create_from_scm(
    ownername="myusername",
    projectname="my-awesome-project",
    clone_url="https://github.com/user/mypackage.git",
    committish="v1.0.0",  # branch, tag, or commit hash
    subdirectory="",  # subdirectory containing the spec file
    spec="mypackage.spec",  # path to spec file
    scm_type="git",
    source_build_method="rpkg",  # or "tito", "make_srpm"
)

print(f"Build submitted: {build.id}")
print(f"Clone URL: {build.source_package.url}")

Build from PyPI

from copr.v3 import Client

client = Client.create_from_config_file()

# Build a Python package from PyPI
build = client.build_proxy.create_from_pypi(
    ownername="myusername",
    projectname="my-awesome-project",
    pypi_package_name="requests",
    pypi_package_version="2.31.0",  # or None for latest
    python_versions=[3],  # Python versions to build for
)

print(f"PyPI build created: {build.id}")

Build with Custom Options

from copr.v3 import Client

client = Client.create_from_config_file()

# Build with specific chroots and options
buildopts = {
    "chroots": ["fedora-39-x86_64"],  # Override project chroots
    "background": False,  # Normal priority build
    "timeout": 3600,  # 1 hour timeout
}

build = client.build_proxy.create_from_url(
    ownername="myusername",
    projectname="my-awesome-project",
    url="https://example.com/package.src.rpm",
    buildopts=buildopts,
)

print(f"Build submitted with custom options: {build.id}")

Multiple Builds from URLs

from copr.v3 import Client

client = Client.create_from_config_file()

# Submit multiple SRPMs at once
urls = [
    "https://example.com/package1-1.0-1.src.rpm",
    "https://example.com/package2-2.0-1.src.rpm",
    "https://example.com/package3-3.0-1.src.rpm",
]

builds = client.build_proxy.create_from_urls(
    ownername="myusername",
    projectname="my-awesome-project",
    urls=urls,
)

for build in builds:
    print(f"Build {build.id} submitted")

Monitoring Builds

Checking Build Status

from copr.v3 import Client

client = Client.create_from_config_file()

# Get build information
build = client.build_proxy.get(12345)

print(f"Build ID: {build.id}")
print(f"State: {build.state}")  # importing, pending, running, succeeded, failed, etc.
print(f"Project: {build.projectname}")
print(f"Package: {build.source_package.name}")
print(f"Submitted: {build.submitted_on}")

Waiting for Build Completion

from copr.v3 import Client, wait

client = Client.create_from_config_file()

build = client.build_proxy.create_from_url(
    "myusername", "my-awesome-project",
    "https://example.com/package.src.rpm"
)

print(f"Waiting for build {build.id}...")
results = wait(build, interval=30)
print(f"Build finished: {results[0].state}")

Listing Builds

from copr.v3 import Client

client = Client.create_from_config_file()

# Get all builds for a project
builds = client.build_proxy.get_list(
    ownername="myusername",
    projectname="my-awesome-project",
)

for build in builds:
    print(f"Build {build.id}: {build.source_package.name} - {build.state}")

Filtering Builds

from copr.v3 import Client

client = Client.create_from_config_file()

# Get only failed builds
builds = client.build_proxy.get_list(
    ownername="myusername",
    projectname="my-awesome-project",
    status="failed",
)

for build in builds:
    print(f"Failed build {build.id}: {build.source_package.name}")

Canceling a Build

from copr.v3 import Client

client = Client.create_from_config_file()

# Cancel a running build
result = client.build_proxy.cancel(12345)
print(f"Build canceled: {result.state}")

Deleting Builds

from copr.v3 import Client

client = Client.create_from_config_file()

# Delete a single build
client.build_proxy.delete(12345)
print("Build deleted")

# Delete multiple builds
build_ids = [12345, 12346, 12347]
client.build_proxy.delete_list(build_ids)
print(f"Deleted {len(build_ids)} builds")

Package Management

Adding a Package Configuration

from copr.v3 import Client

client = Client.create_from_config_file()

# Add a package with Git source
package = client.package_proxy.add(
    ownername="myusername",
    projectname="my-awesome-project",
    packagename="mypackage",
    source_type="git",
    source_dict={
        "clone_url": "https://github.com/user/mypackage.git",
        "committish": "main",
        "subdirectory": "",
        "spec": "mypackage.spec",
        "type": "rpkg",
    },
)

print(f"Package added: {package.name}")

Building from Package Configuration

from copr.v3 import Client

client = Client.create_from_config_file()

# Build using stored package configuration
build = client.package_proxy.build(
    ownername="myusername",
    projectname="my-awesome-project",
    packagename="mypackage",
)

print(f"Build created from package config: {build.id}")

Listing Packages

from copr.v3 import Client

client = Client.create_from_config_file()

# List all packages in a project
packages = client.package_proxy.get_list(
    ownername="myusername",
    projectname="my-awesome-project",
    with_latest_build=True,  # Include latest build info
)

for package in packages:
    print(f"Package: {package.name}")
    if hasattr(package, 'builds'):
        print(f"  Latest build: {package.builds.latest.id}")

Editing Package Configuration

from copr.v3 import Client

client = Client.create_from_config_file()

# Update package source configuration
package = client.package_proxy.edit(
    ownername="myusername",
    projectname="my-awesome-project",
    packagename="mypackage",
    source_dict={
        "committish": "develop",  # Change to develop branch
    },
)

print(f"Package updated: {package.name}")

Deleting a Package

from copr.v3 import Client

client = Client.create_from_config_file()

# Remove package from project
client.package_proxy.delete(
    ownername="myusername",
    projectname="my-awesome-project",
    packagename="old-package",
)

print("Package deleted")

Advanced Workflows

Automated Build Pipeline

from copr.v3 import Client, wait, succeeded
import sys

def build_pipeline(project_owner, project_name, git_url, git_tag):
    """Complete build pipeline with error handling"""
    client = Client.create_from_config_file()
    
    try:
        # Create build from Git
        print(f"Starting build from {git_url}@{git_tag}")
        build = client.build_proxy.create_from_scm(
            ownername=project_owner,
            projectname=project_name,
            clone_url=git_url,
            committish=git_tag,
            spec="package.spec",
        )
        
        print(f"Build {build.id} submitted, waiting for completion...")
        
        # Wait for build with progress updates
        def progress(builds):
            print(f"  State: {builds[0].state}")
        
        results = wait(build, interval=30, callback=progress, timeout=7200)
        
        # Check results
        if succeeded(results):
            print(f"✓ Build {results[0].id} succeeded!")
            print(f"  Package: {results[0].source_package.name}")
            return 0
        else:
            print(f"✗ Build {results[0].id} failed")
            print(f"  State: {results[0].state}")
            return 1
            
    except Exception as e:
        print(f"✗ Error: {e}")
        return 2

if __name__ == "__main__":
    exit_code = build_pipeline(
        project_owner="myusername",
        project_name="my-awesome-project",
        git_url="https://github.com/user/repo.git",
        git_tag="v1.0.0",
    )
    sys.exit(exit_code)

Batch Build Multiple Packages

from copr.v3 import Client, wait, succeeded

client = Client.create_from_config_file()

packages = [
    {"name": "pkg1", "url": "https://example.com/pkg1.src.rpm"},
    {"name": "pkg2", "url": "https://example.com/pkg2.src.rpm"},
    {"name": "pkg3", "url": "https://example.com/pkg3.src.rpm"},
]

builds = []
for pkg in packages:
    print(f"Submitting {pkg['name']}...")
    build = client.build_proxy.create_from_url(
        ownername="myusername",
        projectname="my-awesome-project",
        url=pkg['url'],
    )
    builds.append(build)
    print(f"  Build ID: {build.id}")

print(f"\nWaiting for {len(builds)} builds to complete...")
results = wait(builds, interval=30)

print("\nResults:")
for i, result in enumerate(results):
    status = "✓" if result.state == "succeeded" else "✗"
    print(f"{status} {packages[i]['name']}: {result.state}")

if succeeded(results):
    print("\nAll builds succeeded!")
else:
    print("\nSome builds failed")

Clone and Customize Project

from copr.v3 import Client

client = Client.create_from_config_file()

# Fork an existing project
original_owner = "upstream-user"
original_project = "upstream-project"

print(f"Forking {original_owner}/{original_project}...")
forked = client.project_proxy.fork(
    ownername=original_owner,
    projectname=original_project,
    dstownername="myusername",
    dstprojectname="my-fork",
)

print(f"Forked to {forked.full_name}")

# Customize the fork
print("Customizing fork...")
client.project_proxy.edit(
    ownername="myusername",
    projectname="my-fork",
    description="My customized fork of upstream-project",
    enable_net=True,
    chroots=["fedora-40-x86_64"],  # Only build for F40
)

print("Fork customized successfully")

Error Handling and Retries

from copr.v3 import Client, CoprRequestException, CoprAuthException
import time

def create_build_with_retry(ownername, projectname, url, max_retries=3):
    """Create build with automatic retry on failure"""
    client = Client.create_from_config_file()
    
    for attempt in range(max_retries):
        try:
            print(f"Attempt {attempt + 1}/{max_retries}")
            build = client.build_proxy.create_from_url(
                ownername=ownername,
                projectname=projectname,
                url=url,
            )
            print(f"Build created: {build.id}")
            return build
            
        except CoprAuthException as e:
            print(f"Authentication error: {e}")
            return None  # Don't retry auth errors
            
        except CoprRequestException as e:
            print(f"Request failed: {e}")
            if attempt < max_retries - 1:
                wait_time = 2 ** attempt  # Exponential backoff
                print(f"Retrying in {wait_time} seconds...")
                time.sleep(wait_time)
            else:
                print("Max retries reached")
                return None
                
        except Exception as e:
            print(f"Unexpected error: {e}")
            return None
    
    return None

# Use the retry function
build = create_build_with_retry(
    "myusername",
    "my-awesome-project",
    "https://example.com/package.src.rpm",
)

if build:
    print(f"Success! Build ID: {build.id}")
else:
    print("Failed to create build")

Working with Chroots

Listing Available Chroots

from copr.v3 import Client

client = Client.create_from_config_file()

# Get all available chroots
chroots = client.mock_chroot_proxy.get_list()

print("Available chroots:")
for chroot in chroots:
    print(f"  - {chroot.name}")

Filtering Chroots

from copr.v3 import Client

client = Client.create_from_config_file()

chroots = client.mock_chroot_proxy.get_list()

# Filter for Fedora 39 chroots only
fedora_39 = [c for c in chroots if "fedora-39" in c.name]

print("Fedora 39 chroots:")
for chroot in fedora_39:
    print(f"  - {chroot.name}")

Tips and Best Practices

Always use wait() when you need to ensure builds complete before proceeding. This is essential for CI/CD pipelines.
Use the succeeded() helper function to quickly check if all builds in a batch completed successfully.
Build IDs are unique across the entire Copr instance, not just within your project.
When building from Git, use specific tags or commit hashes for reproducible builds instead of branch names.
The Munch objects returned by API calls support both dictionary and attribute access. Use whichever style you prefer.

Build docs developers (and LLMs) love