commit
aa1173f7d9
@ -0,0 +1 @@
|
||||
__pycache__
|
@ -0,0 +1,408 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
import argparse
|
||||
import logging
|
||||
from datetime import datetime
|
||||
import tarfile
|
||||
import shutil
|
||||
from git import Repo, GitCommandError
|
||||
import tempfile
|
||||
from concurrent.futures import ThreadPoolExecutor, wait, FIRST_COMPLETED
|
||||
import fnmatch
|
||||
import re
|
||||
from debian.copyright import Header, Copyright
|
||||
import uuid
|
||||
from common import clean_old_logs
|
||||
|
||||
BASE_DIR = "/srv/lubuntu-ci/repos"
|
||||
DEBFULLNAME = "Lugito"
|
||||
DEBEMAIL = "info@lubuntu.me"
|
||||
OUTPUT_DIR = os.path.join(BASE_DIR, "build_output")
|
||||
SUPPRESSED_LINTIAN_TAGS = [
|
||||
"orig-tarball-missing-upstream-signature",
|
||||
"package-has-long-file-name",
|
||||
"adopted-extended-field"
|
||||
]
|
||||
BASE_OUTPUT_DIR = "/srv/lubuntu-ci/output"
|
||||
LOG_DIR = os.path.join(BASE_OUTPUT_DIR, "logs", "source_builds")
|
||||
BASE_LINTIAN_DIR = os.path.join(BASE_OUTPUT_DIR, f"lintian.tmp.{str(uuid.uuid4())[:8]}")
|
||||
REAL_LINTIAN_DIR = os.path.join(BASE_OUTPUT_DIR, "lintian")
|
||||
|
||||
os.makedirs(LOG_DIR, exist_ok=True)
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
os.makedirs(BASE_LINTIAN_DIR, exist_ok=True)
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||
handlers=[
|
||||
logging.FileHandler(log_file),
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
logger = logging.getLogger("TimeBasedLogger")
|
||||
|
||||
def run_command(cmd, cwd=None, env=None, show_output=False):
|
||||
logging.info(f"Executing: {' '.join(cmd)} in {cwd or 'current directory'}")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
cwd=cwd,
|
||||
env=env,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
if show_output:
|
||||
if result.stdout:
|
||||
logging.info(f"Output: {result.stdout.strip()}")
|
||||
if result.stderr:
|
||||
logging.warning(f"Output: {result.stderr.strip()}")
|
||||
logging.info(f"Command succeeded: {' '.join(cmd)}")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logging.error(f"Command failed: {' '.join(cmd)}")
|
||||
logging.error(e.stderr)
|
||||
raise
|
||||
|
||||
def parse_version(changelog_path):
|
||||
try:
|
||||
with open(changelog_path, "r") as f:
|
||||
first_line = f.readline().strip()
|
||||
version_match = first_line.split("(")[1].split(")")[0]
|
||||
# Remove Debian revision
|
||||
upstream_version = version_match.split("-")[0]
|
||||
# Remove '+git...' and '~release' if present
|
||||
upstream_version = re.sub(r'(\+git[0-9]+)?(~[a-z]+)?$', '', upstream_version)
|
||||
logging.info(f"Upstream version extracted: {upstream_version}")
|
||||
current_date = datetime.now().strftime("%Y%m%d%H%M")
|
||||
version = f"{upstream_version}+git{current_date}"
|
||||
logging.info(f"Parsed VERSION: {version}")
|
||||
return version
|
||||
except (IndexError, FileNotFoundError) as e:
|
||||
logging.error(f"Error parsing version from {changelog_path}: {e}")
|
||||
raise
|
||||
|
||||
def get_exclusions(packaging):
|
||||
exclusions = []
|
||||
with io.open(os.path.join(packaging, "debian/copyright"), "rt", encoding="utf-8") as f:
|
||||
copyright_obj = Copyright(f)
|
||||
for paragraph in copyright_obj.all_paragraphs():
|
||||
if isinstance(paragraph, Header):
|
||||
if paragraph.files_excluded:
|
||||
for file_name in paragraph.files_excluded:
|
||||
exclusions.append(file_name)
|
||||
break
|
||||
return exclusions
|
||||
|
||||
def create_tarball(name, source_dir, exclusions=[]):
|
||||
tar_filename = f"{name}_MAIN.orig.tar.gz"
|
||||
logging.info(f"Creating tarball: {tar_filename}")
|
||||
exclusions.append(".git/")
|
||||
|
||||
def exclusion_func(tarinfo):
|
||||
for exclusion in exclusions:
|
||||
if exclusion in tarinfo.name:
|
||||
return None
|
||||
|
||||
return tarinfo
|
||||
|
||||
with tarfile.open(tar_filename, "w:gz") as tar:
|
||||
tar.add(source_dir, arcname=os.path.basename(source_dir), filter=exclusion_func)
|
||||
logging.info(f"Tarball created and compressed: {tar_filename}")
|
||||
|
||||
def update_changelog(packaging_dir, release, version, env):
|
||||
name = os.path.basename(packaging_dir)
|
||||
logging.info(f"Updating changelog for {name} to version {version}-0ubuntu1~ppa1")
|
||||
run_command(["git", "checkout", "debian/changelog"], cwd=packaging_dir)
|
||||
cmd = [
|
||||
"dch",
|
||||
"--distribution", release,
|
||||
"--package", name,
|
||||
"--newversion", f"{version}-0ubuntu1~ppa1",
|
||||
"--urgency", "low",
|
||||
"CI upload."
|
||||
]
|
||||
run_command(cmd, cwd=packaging_dir, env=env)
|
||||
|
||||
def build_package(packaging_dir, env):
|
||||
name = os.path.basename(packaging_dir)
|
||||
logging.info(f"Building source package for {name}")
|
||||
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
try:
|
||||
temp_packaging_dir = os.path.join(temp_dir, name)
|
||||
os.makedirs(temp_packaging_dir, exist_ok=True)
|
||||
shutil.copytree(packaging_dir + "/debian", temp_packaging_dir + "/debian")
|
||||
|
||||
tarball_name = f"{name}_{env['VERSION']}.orig.tar.gz"
|
||||
tarball_source = os.path.join(BASE_DIR, tarball_name)
|
||||
tarball_dest = os.path.join(temp_dir, tarball_name)
|
||||
shutil.copyfile(tarball_source, tarball_dest)
|
||||
|
||||
cmd_build = ["debuild", "--no-lintian", "-S", "-d", "-sa"]
|
||||
run_command(cmd_build, cwd=temp_packaging_dir, env=env)
|
||||
run_command(["git", "checkout", "debian/changelog"], cwd=packaging_dir)
|
||||
|
||||
pattern = f"{name}_{env['VERSION']}*"
|
||||
for filename in os.listdir(temp_dir):
|
||||
if fnmatch.fnmatch(filename, pattern):
|
||||
source_file = os.path.join(temp_dir, filename)
|
||||
dest_file = os.path.join(OUTPUT_DIR, filename)
|
||||
shutil.copyfile(source_file, dest_file)
|
||||
logging.info(f"Copied {filename} to {OUTPUT_DIR}")
|
||||
|
||||
changes_files = [f for f in os.listdir(OUTPUT_DIR) if f.startswith(f"{name}_{env['VERSION']}") and f.endswith("_source.changes")]
|
||||
if changes_files:
|
||||
changes_file = os.path.join(OUTPUT_DIR, changes_files[-1])
|
||||
logging.info(f"Built package, changes file: {changes_file}")
|
||||
return changes_file
|
||||
else:
|
||||
logging.error("No changes file found after build.")
|
||||
raise FileNotFoundError("Changes file not found.")
|
||||
finally:
|
||||
shutil.rmtree(temp_dir)
|
||||
|
||||
def load_config(config_path):
|
||||
try:
|
||||
with open(config_path, "r") as f:
|
||||
config = yaml.safe_load(f)
|
||||
if "packages" not in config or "releases" not in config:
|
||||
raise ValueError("Config file must contain 'packages' and 'releases' sections.")
|
||||
return config
|
||||
except Exception as e:
|
||||
logging.error(f"Error loading config file: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def clone_or_update_repo(destination, repo_url, repo_branch=None):
|
||||
if os.path.exists(destination):
|
||||
logging.info(f"Repository already exists at {destination}, checking branch and remote URL.")
|
||||
try:
|
||||
repo = Repo(destination)
|
||||
|
||||
current_remote_url = repo.remotes.origin.url
|
||||
if current_remote_url != repo_url:
|
||||
logging.info(f"Remote URL differs for {destination}. Removing and recloning.")
|
||||
shutil.rmtree(destination)
|
||||
else:
|
||||
repo.git.reset("--hard", "HEAD")
|
||||
current_branch = repo.active_branch.name
|
||||
if repo_branch and current_branch != repo_branch:
|
||||
logging.info(f"Branch differs for {destination}. Removing and recloning.")
|
||||
shutil.rmtree(destination)
|
||||
else:
|
||||
logging.info(f"Repository matches desired remote and branch, pulling updates.")
|
||||
repo.git.checkout(repo_branch or current_branch)
|
||||
try:
|
||||
repo.remotes.origin.pull()
|
||||
repo.submodule_update(recursive=True)
|
||||
logging.info(f"Pulled latest changes for {destination}")
|
||||
except GitCommandError as e:
|
||||
if 'non-fast-forward' in str(e):
|
||||
logging.error(f"Pull failed due to non-fast-forward update: {e}")
|
||||
logging.info(f"Removing repository {destination} and cloning again.")
|
||||
shutil.rmtree(destination)
|
||||
else:
|
||||
logging.error(f"Pull failed for {destination}: {e}")
|
||||
raise
|
||||
else:
|
||||
return
|
||||
except Exception as e:
|
||||
logging.error(f"Error updating repository {destination}: {e}")
|
||||
logging.info(f"Removing repository {destination} and cloning again.")
|
||||
shutil.rmtree(destination)
|
||||
try:
|
||||
logging.info(f"Cloning repository {repo_url} into {destination}")
|
||||
repo = Repo.clone_from(repo_url, destination, recurse_submodules=True)
|
||||
if repo_branch:
|
||||
repo.git.checkout(repo_branch)
|
||||
logging.info(f"Checked out {repo_branch} in {destination}")
|
||||
except GitCommandError as e:
|
||||
logging.error(f"Git clone failed for {repo_url}: {e}")
|
||||
raise
|
||||
|
||||
def publish_lintian():
|
||||
if os.path.exists(BASE_LINTIAN_DIR):
|
||||
for root, dirs, files in os.walk(BASE_LINTIAN_DIR):
|
||||
for file in files:
|
||||
# Determine the source and destination paths
|
||||
src_path = os.path.join(root, file)
|
||||
rel_path = os.path.relpath(src_path, BASE_LINTIAN_DIR)
|
||||
dest_path = os.path.join(REAL_LINTIAN_DIR, rel_path)
|
||||
|
||||
# Ensure the destination directory exists
|
||||
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
|
||||
|
||||
# Copy the file
|
||||
shutil.copy2(src_path, dest_path)
|
||||
|
||||
# Remove the temporary directory
|
||||
shutil.rmtree(BASE_LINTIAN_DIR)
|
||||
|
||||
def run_source_lintian(name, sources_path):
|
||||
logging.info(f"Running Lintian for {name}")
|
||||
with tempfile.NamedTemporaryFile(mode='w+', suffix='.txt') as temp_file:
|
||||
temp_file.write("\n".join(SUPPRESSED_LINTIAN_TAGS))
|
||||
temp_file.flush()
|
||||
temp_file_path = temp_file.name
|
||||
|
||||
cmd = [
|
||||
"lintian",
|
||||
"-EvIL",
|
||||
"+pedantic",
|
||||
"--suppress-tags-from-file",
|
||||
f"{temp_file_path}",
|
||||
sources_path
|
||||
]
|
||||
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
|
||||
stderr, stdout = None, None
|
||||
if result.stderr:
|
||||
stderr = result.stderr.strip()
|
||||
if result.stdout:
|
||||
stdout = result.stdout.strip()
|
||||
|
||||
lintian_output = None
|
||||
if stderr == stdout:
|
||||
lintian_output = stderr
|
||||
else:
|
||||
lintian_output = f"{stderr}\n{stdout}".strip()
|
||||
|
||||
if lintian_output:
|
||||
pkgdir = os.path.join(BASE_LINTIAN_DIR, name)
|
||||
if not os.path.exists(pkgdir):
|
||||
os.mkdir(pkgdir)
|
||||
output_file = os.path.join(pkgdir, "source.txt")
|
||||
with open(output_file, "a") as f:
|
||||
f.write(lintian_output)
|
||||
|
||||
logging.info(f"Lintian run for {name} is complete")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Automate Lubuntu package builds.")
|
||||
parser.add_argument("config", help="Path to the YAML configuration file.")
|
||||
parser.add_argument("--skip-dput", action="store_true", help="Skip the dput upload step.")
|
||||
parser.add_argument("--skip-cleanup", action="store_true", help="Skip removal of build_output.")
|
||||
args = parser.parse_args()
|
||||
|
||||
config = load_config(args.config)
|
||||
packages = config["packages"]
|
||||
releases = config["releases"]
|
||||
|
||||
os.makedirs(BASE_DIR, exist_ok=True)
|
||||
logging.info(f"Using base directory: {BASE_DIR}")
|
||||
os.chdir(BASE_DIR)
|
||||
|
||||
with ThreadPoolExecutor(max_workers=5) as executor:
|
||||
def dput_source(name, upload_target, changes_files, devel_changes_files):
|
||||
if changes_files:
|
||||
hr_changes = ", ".join(changes_files)
|
||||
logging.info(f"Uploading {hr_changes} to {upload_target} using dput")
|
||||
cmd_upload = ["dput", upload_target] + changes_files
|
||||
run_command(cmd_upload, cwd=OUTPUT_DIR)
|
||||
logging.info(f"Completed upload of {hr_changes} to {upload_target}")
|
||||
|
||||
for file in devel_changes_files:
|
||||
if file:
|
||||
futures.add(executor.submit(run_source_lintian, name, file))
|
||||
|
||||
def prepare_package(pkg):
|
||||
name = pkg.get("name")
|
||||
if not name:
|
||||
logging.warning(f"Skipping package due to missing name: {pkg}")
|
||||
return
|
||||
upstream_url = pkg.get("upstream_url") or f"https://github.com/lxqt/{name}.git"
|
||||
upstream_destination = os.path.join(BASE_DIR, f"upstream-{name}")
|
||||
clone_or_update_repo(upstream_destination, upstream_url)
|
||||
packaging_url = pkg.get("packaging_url") or f"https://git.lubuntu.me/Lubuntu/{name}-packaging.git"
|
||||
packaging_branch = pkg.get("packaging_branch") or f"ubuntu/{releases[0]}" if releases else None
|
||||
packaging_destination = os.path.join(BASE_DIR, name)
|
||||
clone_or_update_repo(packaging_destination, packaging_url, packaging_branch)
|
||||
exclusions = get_exclusions(packaging_destination)
|
||||
create_tarball(name, upstream_destination, exclusions)
|
||||
run_command(["update-maintainer"], cwd=packaging_destination)
|
||||
futures.add(executor.submit(process_package, pkg))
|
||||
|
||||
def process_package(pkg):
|
||||
name = pkg.get("name")
|
||||
upload_target = pkg.get("upload_target", "ppa:lubuntu-ci/unstable-ci-proposed")
|
||||
|
||||
if not name:
|
||||
logging.warning(f"Skipping package due to missing name: {pkg}")
|
||||
return []
|
||||
|
||||
package_changes = []
|
||||
|
||||
packaging_destination = os.path.join(BASE_DIR, name)
|
||||
changelog_path = os.path.join(packaging_destination, "debian", "changelog")
|
||||
version = parse_version(changelog_path)
|
||||
|
||||
for release in releases:
|
||||
logging.info(f"Building {name} for {release}")
|
||||
try:
|
||||
release_version = f"{version}~{release}"
|
||||
tarball_name = f"{name}_{release_version}.orig.tar.gz"
|
||||
tarball_source = os.path.join(BASE_DIR, f"{name}_MAIN.orig.tar.gz")
|
||||
tarball_dest = os.path.join(BASE_DIR, tarball_name)
|
||||
shutil.copyfile(tarball_source, tarball_dest)
|
||||
|
||||
env = os.environ.copy()
|
||||
env["DEBFULLNAME"] = DEBFULLNAME
|
||||
env["DEBEMAIL"] = DEBEMAIL
|
||||
env["VERSION"] = release_version
|
||||
env["UPLOAD_TARGET"] = upload_target
|
||||
|
||||
# Update changelog and build package
|
||||
update_changelog(packaging_destination, release, release_version, env)
|
||||
changes_file = build_package(packaging_destination, env)
|
||||
if changes_file:
|
||||
package_changes.append((changes_file, env))
|
||||
os.remove(os.path.join(BASE_DIR, tarball_name))
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error processing package '{name}' for release '{release}': {e}")
|
||||
|
||||
changes_files = [os.path.basename(cf) for cf, env in package_changes]
|
||||
devel_changes_files = set(os.path.join(OUTPUT_DIR, file) if releases[0] in file else None for file in changes_files)
|
||||
if args.skip_dput:
|
||||
for changes_file in devel_changes_files:
|
||||
if changes_file:
|
||||
futures.add(executor.submit(run_source_lintian, name, changes_file))
|
||||
else:
|
||||
upload_target = package_changes[0][1]["UPLOAD_TARGET"]
|
||||
futures.add(executor.submit(dput_source, name, upload_target, changes_files, devel_changes_files))
|
||||
|
||||
os.remove(os.path.join(BASE_DIR, f"{name}_MAIN.orig.tar.gz"))
|
||||
|
||||
futures = set(executor.submit(prepare_package, pkg) for pkg in packages)
|
||||
|
||||
while futures:
|
||||
done, not_done = wait(futures, return_when=FIRST_COMPLETED)
|
||||
|
||||
for future in done:
|
||||
try:
|
||||
result = future.result()
|
||||
except Exception as e:
|
||||
logging.exception("Task generated an exception")
|
||||
finally:
|
||||
futures.remove(future)
|
||||
|
||||
if not args.skip_cleanup:
|
||||
shutil.rmtree(OUTPUT_DIR)
|
||||
logging.info("Publishing Lintian output...")
|
||||
publish_lintian()
|
||||
clean_old_logs(LOG_DIR)
|
||||
|
||||
logging.info("Script completed successfully.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2024 Simon Quigley <tsimonq2@ubuntu.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
def clean_old_logs(log_dir, max_age_seconds=86400):
|
||||
now = datetime.utcnow()
|
||||
for file_name in os.listdir(log_dir):
|
||||
file_path = os.path.join(log_dir, file_name)
|
||||
if os.path.isfile(file_path):
|
||||
file_age = now - os.path.getmtime(file_path)
|
||||
if file_age > max_age_seconds:
|
||||
os.remove(file_path)
|
@ -0,0 +1,126 @@
|
||||
# Configuration file for britney
|
||||
|
||||
# Paths for control files
|
||||
TESTING = data/%(SERIES)
|
||||
UNSTABLE = data/%(SERIES)-proposed
|
||||
PARTIAL_UNSTABLE = yes
|
||||
|
||||
# Output
|
||||
NONINST_STATUS = data/%(SERIES)/non-installable-status
|
||||
EXCUSES_OUTPUT = output/%(SERIES)/excuses.html
|
||||
EXCUSES_YAML_OUTPUT = output/%(SERIES)/excuses.yaml.xz
|
||||
UPGRADE_OUTPUT = output/%(SERIES)/output.txt
|
||||
HEIDI_OUTPUT = output/%(SERIES)/HeidiResult
|
||||
|
||||
# External policy/constraints/faux-packages information that
|
||||
# (presumably) rarely changes. Examples include "constraints".
|
||||
STATIC_INPUT_DIR = data/%(SERIES)/input
|
||||
|
||||
# Directory for input files that Britney will update herself
|
||||
# (e.g. aging information) or will need regular updates
|
||||
# (e.g. urgency information).
|
||||
STATE_DIR = data/%(SERIES)/state
|
||||
|
||||
# List of architectures that Britney should consider.
|
||||
# - defaults to the value in testing's Release file (if it is present).
|
||||
# - Required for the legacy layout.
|
||||
ARCHITECTURES = amd64 arm64 armhf ppc64el riscv64 s390x
|
||||
|
||||
# if you're not in this list, arch: all packages are allowed to break on you
|
||||
NOBREAKALL_ARCHES = amd64
|
||||
|
||||
# primary architecture used for checking Build-Depends-Indep
|
||||
ALL_BUILDARCH = amd64
|
||||
|
||||
# is arch-all built separately? i.e. can it fail independently of another arch?
|
||||
HAS_ARCH_ALL_BUILDDS = no
|
||||
|
||||
# if you're in this list, your packages may not stay in sync with the source
|
||||
OUTOFSYNC_ARCHES =
|
||||
|
||||
# if you're in this list, your uninstallability count may increase
|
||||
BREAK_ARCHES =
|
||||
|
||||
# if you're in this list, you are a new architecture
|
||||
NEW_ARCHES =
|
||||
|
||||
# priorities and delays
|
||||
MINDAYS_LOW = 0
|
||||
MINDAYS_MEDIUM = 0
|
||||
MINDAYS_HIGH = 0
|
||||
MINDAYS_CRITICAL = 0
|
||||
MINDAYS_EMERGENCY = 0
|
||||
DEFAULT_URGENCY = medium
|
||||
NO_PENALTIES = high critical emergency
|
||||
BOUNTY_MIN_AGE = 2
|
||||
|
||||
HINTSDIR = data/%(SERIES)-proposed/Hints
|
||||
|
||||
# hint permissions
|
||||
HINTS_LANEY = ALL
|
||||
HINTS_STEFANOR = ALL
|
||||
HINTS_STGRABER = ALL
|
||||
HINTS_VORLON = ALL
|
||||
HINTS_PITTI = ALL
|
||||
HINTS_UBUNTU-RELEASE = ALL
|
||||
# Kernel team automated testing
|
||||
HINTS_KERNEL-TESTING = block unblock
|
||||
# SRU team
|
||||
HINTS_APW = ALL
|
||||
HINTS_ARGES = ALL
|
||||
HINTS_BRIAN-MURRAY = ALL
|
||||
HINTS_RACB = ALL
|
||||
HINTS_RAOF = ALL
|
||||
HINTS_SIL2100 = ALL
|
||||
HINTS_TJAALTON = ALL
|
||||
HINTS_UBUNTU-SRU = ALL
|
||||
HINTS_FREEZE = block block-all
|
||||
|
||||
# support for old libraries in testing (smooth update)
|
||||
# use ALL to enable smooth updates for all the sections
|
||||
#
|
||||
# naming a non-existent section will effectively disable new smooth
|
||||
# updates but still allow removals to occur
|
||||
SMOOTH_UPDATES = libs oldlibs
|
||||
|
||||
IGNORE_CRUFT = 0
|
||||
|
||||
REMOVE_OBSOLETE = no
|
||||
|
||||
CHECK_BUILDD = nxo
|
||||
|
||||
IMPLICIT_DEPS = no
|
||||
|
||||
ADT_ENABLE = no
|
||||
#ADT_ARCHES = amd64 i386 armhf ppc64el arm64
|
||||
#ADT_AMQP = amqp://test_request:password@autopkgtest-amqp.internal
|
||||
# space separate list of PPAs to add for test requests and for polling results;
|
||||
# the *last* one determines the swift container name
|
||||
ADT_PPAS =
|
||||
# set this to the path of a (r/o) autopkgtest-results.cache for running many parallel
|
||||
# britney instances for PPAs without updating the cache
|
||||
ADT_SHARED_RESULTS_CACHE =
|
||||
# Swift base URL with the results (must be publicly readable and browsable)
|
||||
# or file location if results are pre-fetched
|
||||
#ADT_SWIFT_URL = https://objectstorage.prodstack5.canonical.com/swift/v1/AUTH_0f9aae918d5b4744bf7b827671c86842/
|
||||
# Base URL for autopkgtest site, used for links in the excuses
|
||||
#ADT_CI_URL = https://autopkgtest.ubuntu.com/
|
||||
# URL for the autopkgtest database, if used
|
||||
#ADT_DB_URL = https://autopkgtest.ubuntu.com/static/autopkgtest.db
|
||||
#ADT_HUGE = 20
|
||||
|
||||
# Autopkgtest results can be used to influence the aging
|
||||
ADT_REGRESSION_PENALTY =
|
||||
ADT_SUCCESS_BOUNTY =
|
||||
ADT_BASELINE = reference
|
||||
ADT_RETRY_URL_MECH =
|
||||
ADT_RETRY_OLDER_THAN =
|
||||
ADT_REFERENCE_MAX_AGE =
|
||||
|
||||
# email uploaders for stuck uploads
|
||||
EMAIL_ENABLE = no
|
||||
# email SRU bugs when regressions are detected
|
||||
SRUREGRESSIONEMAIL_ENABLE = no
|
||||
|
||||
# we don't run piuparts testing in Ubuntu
|
||||
PIUPARTS_ENABLE = no
|
@ -0,0 +1,10 @@
|
||||
packages:
|
||||
- name: cmake
|
||||
upstream_url: "https://gitlab.kitware.com/cmake/cmake.git"
|
||||
packaging_url: "https://git.lubuntu.me/Lubuntu/cmake.git"
|
||||
packaging_branch: "ci/unstable"
|
||||
|
||||
releases:
|
||||
- plucky
|
||||
- oracular
|
||||
- noble
|
@ -0,0 +1,306 @@
|
||||
packages:
|
||||
- name: kf6-extra-cmake-modules
|
||||
upstream_url: "https://invent.kde.org/frameworks/extra-cmake-modules.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-extra-cmake-modules"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-attica
|
||||
upstream_url: "https://invent.kde.org/frameworks/attica.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-attica"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-baloo
|
||||
upstream_url: "https://invent.kde.org/frameworks/baloo.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-baloo"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-bluez-qt
|
||||
upstream_url: "https://invent.kde.org/frameworks/bluez-qt.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-bluez-qt"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-breeze-icons
|
||||
upstream_url: "https://invent.kde.org/frameworks/breeze-icons.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-breeze-icons"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-frameworkintegration
|
||||
upstream_url: "https://invent.kde.org/frameworks/frameworkintegration.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-frameworkintegration"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kapidox
|
||||
upstream_url: "https://invent.kde.org/frameworks/kapidox.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kapidox"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-karchive
|
||||
upstream_url: "https://invent.kde.org/frameworks/karchive.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-karchive"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kauth
|
||||
upstream_url: "https://invent.kde.org/frameworks/kauth.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kauth"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kbookmarks
|
||||
upstream_url: "https://invent.kde.org/frameworks/kbookmarks.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kbookmarks"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kcalendarcore
|
||||
upstream_url: "https://invent.kde.org/frameworks/kcalendarcore.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kcalendarcore"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kcmutils
|
||||
upstream_url: "https://invent.kde.org/frameworks/kcmutils.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kcmutils"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kcodecs
|
||||
upstream_url: "https://invent.kde.org/frameworks/kcodecs.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kcodecs"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kcolorscheme
|
||||
upstream_url: "https://invent.kde.org/frameworks/kcolorscheme.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kcolorscheme"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kcompletion
|
||||
upstream_url: "https://invent.kde.org/frameworks/kcompletion.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kcompletion"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kconfig
|
||||
upstream_url: "https://invent.kde.org/frameworks/kconfig.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kconfig"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kconfigwidgets
|
||||
upstream_url: "https://invent.kde.org/frameworks/kconfigwidgets.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kconfigwidgets"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kcoreaddons
|
||||
upstream_url: "https://invent.kde.org/frameworks/kcoreaddons.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kcoreaddons"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kcrash
|
||||
upstream_url: "https://invent.kde.org/frameworks/kcrash.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kcrash"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kdbusaddons
|
||||
upstream_url: "https://invent.kde.org/frameworks/kdbusaddons.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kdbusaddons"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kdeclarative
|
||||
upstream_url: "https://invent.kde.org/frameworks/kdeclarative.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kdeclarative"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kded
|
||||
upstream_url: "https://invent.kde.org/frameworks/kded.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kded"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kdesu
|
||||
upstream_url: "https://invent.kde.org/frameworks/kdesu.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kdesu"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kdnssd
|
||||
upstream_url: "https://invent.kde.org/frameworks/kdnssd.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kdnssd"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kdoctools
|
||||
upstream_url: "https://invent.kde.org/frameworks/kdoctools.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kdoctools"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kfilemetadata
|
||||
upstream_url: "https://invent.kde.org/frameworks/kfilemetadata.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kfilemetadata"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kglobalaccel
|
||||
upstream_url: "https://invent.kde.org/frameworks/kglobalaccel.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kglobalaccel"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kguiaddons
|
||||
upstream_url: "https://invent.kde.org/frameworks/kguiaddons.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kguiaddons"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kholidays
|
||||
upstream_url: "https://invent.kde.org/frameworks/kholidays.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kholidays"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-ki18n
|
||||
upstream_url: "https://invent.kde.org/frameworks/ki18n.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-ki18n"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kiconthemes
|
||||
upstream_url: "https://invent.kde.org/frameworks/kiconthemes.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kiconthemes"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kidletime
|
||||
upstream_url: "https://invent.kde.org/frameworks/kidletime.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kidletime"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kimageformats
|
||||
upstream_url: "https://invent.kde.org/frameworks/kimageformats.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kimageformats"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kio
|
||||
upstream_url: "https://invent.kde.org/frameworks/kio.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kio"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kirigami
|
||||
upstream_url: "https://invent.kde.org/frameworks/kirigami.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kirigami"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kitemmodels
|
||||
upstream_url: "https://invent.kde.org/frameworks/kitemmodels.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kitemmodels"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kitemviews
|
||||
upstream_url: "https://invent.kde.org/frameworks/kitemviews.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kitemviews"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kjobwidgets
|
||||
upstream_url: "https://invent.kde.org/frameworks/kjobwidgets.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kjobwidgets"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-knewstuff
|
||||
upstream_url: "https://invent.kde.org/frameworks/knewstuff.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-knewstuff"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-knotifications
|
||||
upstream_url: "https://invent.kde.org/frameworks/knotifications.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-knotifications"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-knotifyconfig
|
||||
upstream_url: "https://invent.kde.org/frameworks/knotifyconfig.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-knotifyconfig"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kpackage
|
||||
upstream_url: "https://invent.kde.org/frameworks/kpackage.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kpackage"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kparts
|
||||
upstream_url: "https://invent.kde.org/frameworks/kparts.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kparts"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kpeople
|
||||
upstream_url: "https://invent.kde.org/frameworks/kpeople.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kpeople"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kplotting
|
||||
upstream_url: "https://invent.kde.org/frameworks/kplotting.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kplotting"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kpty
|
||||
upstream_url: "https://invent.kde.org/frameworks/kpty.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kpty"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kquickcharts
|
||||
upstream_url: "https://invent.kde.org/frameworks/kquickcharts.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kquickcharts"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-krunner
|
||||
upstream_url: "https://invent.kde.org/frameworks/krunner.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-krunner"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kservice
|
||||
upstream_url: "https://invent.kde.org/frameworks/kservice.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kservice"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kstatusnotifieritem
|
||||
upstream_url: "https://invent.kde.org/frameworks/kstatusnotifieritem.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kstatusnotifieritem"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-ksvg
|
||||
upstream_url: "https://invent.kde.org/frameworks/ksvg.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-ksvg"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-ktexteditor
|
||||
upstream_url: "https://invent.kde.org/frameworks/ktexteditor.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-ktexteditor"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-ktexttemplate
|
||||
upstream_url: "https://invent.kde.org/frameworks/ktexttemplate.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-ktexttemplate"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-ktextwidgets
|
||||
upstream_url: "https://invent.kde.org/frameworks/ktextwidgets.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-ktextwidgets"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kunitconversion
|
||||
upstream_url: "https://invent.kde.org/frameworks/kunitconversion.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kunitconversion"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kuserfeedback
|
||||
upstream_url: "https://invent.kde.org/frameworks/kuserfeedback.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kuserfeedback"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kwallet
|
||||
upstream_url: "https://invent.kde.org/frameworks/kwallet.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kwallet"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kwidgetsaddons
|
||||
upstream_url: "https://invent.kde.org/frameworks/kwidgetsaddons.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kwidgetsaddons"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kwindowsystem
|
||||
upstream_url: "https://invent.kde.org/frameworks/kwindowsystem.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kwindowsystem"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-kxmlgui
|
||||
upstream_url: "https://invent.kde.org/frameworks/kxmlgui.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-kxmlgui"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-modemmanager-qt
|
||||
upstream_url: "https://invent.kde.org/frameworks/modemmanager-qt.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-modemmanager-qt"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-networkmanager-qt
|
||||
upstream_url: "https://invent.kde.org/frameworks/networkmanager-qt.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-networkmanager-qt"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-prison
|
||||
upstream_url: "https://invent.kde.org/frameworks/prison.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-prison"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-purpose
|
||||
upstream_url: "https://invent.kde.org/frameworks/purpose.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-purpose"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-qqc2-desktop-style
|
||||
upstream_url: "https://invent.kde.org/frameworks/qqc2-desktop-style.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-qqc2-desktop-style"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-solid
|
||||
upstream_url: "https://invent.kde.org/frameworks/solid.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-solid"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-sonnet
|
||||
upstream_url: "https://invent.kde.org/frameworks/sonnet.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-sonnet"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-syndication
|
||||
upstream_url: "https://invent.kde.org/frameworks/syndication.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-syndication"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-syntax-highlighting
|
||||
upstream_url: "https://invent.kde.org/frameworks/syntax-highlighting.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-syntax-highlighting"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kf6-threadweaver
|
||||
upstream_url: "https://invent.kde.org/frameworks/threadweaver.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kf6-threadweaver"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: kpmcore
|
||||
upstream_url: "https://invent.kde.org/system/kpmcore.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/kpmcore"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: plasma-discover
|
||||
upstream_url: "https://invent.kde.org/plasma/discover.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/discover"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: skanlite
|
||||
upstream_url: "https://invent.kde.org/graphics/skanlite.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/skanlite"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: libksane
|
||||
upstream_url: "https://invent.kde.org/graphics/libksane.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/libksane"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
- name: ksanecore
|
||||
upstream_url: "https://invent.kde.org/libraries/ksanecore.git"
|
||||
packaging_url: "https://git.launchpad.net/~kubuntu-packagers/kubuntu-packaging/+git/ksanecore"
|
||||
packaging_branch: "kubuntu_unstable"
|
||||
|
||||
releases:
|
||||
- plucky
|
||||
- oracular
|
||||
- noble
|
@ -0,0 +1,45 @@
|
||||
packages:
|
||||
- name: lxqt-build-tools
|
||||
- name: libdbusmenu-lxqt
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: libqtxdg
|
||||
- name: lxqt-menu-data
|
||||
- name: liblxqt
|
||||
- name: libsysstat
|
||||
- name: qtxdg-tools
|
||||
- name: libfm-qt
|
||||
- name: lxqt-globalkeys
|
||||
- name: lxqt-qtplugin
|
||||
- name: qtermwidget
|
||||
- name: lxqt-panel
|
||||
- name: pcmanfm-qt
|
||||
- name: qterminal
|
||||
- name: lxqt-powermanagement
|
||||
- name: lxqt-runner
|
||||
- name: lxqt-themes
|
||||
- name: lxqt-admin
|
||||
- name: lxqt-notificationd
|
||||
- name: lxqt-about
|
||||
- name: lxqt-config
|
||||
- name: lxqt-policykit
|
||||
- name: lxqt-sudo
|
||||
- name: lxqt-openssh-askpass
|
||||
- name: lxqt-session
|
||||
- name: pavucontrol-qt
|
||||
- name: xdg-desktop-portal-lxqt
|
||||
- name: lxqt-archiver
|
||||
- name: screengrab
|
||||
- name: lximage-qt
|
||||
- name: qps
|
||||
- name: obconf-qt
|
||||
- name: nm-tray
|
||||
upstream_url: "https://github.com/palinek/nm-tray.git"
|
||||
- name: calamares
|
||||
upstream_url: "https://github.com/calamares/calamares.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/ubuntu/+source/calamares/+git/calamares"
|
||||
packaging_branch: "ci/unstable"
|
||||
|
||||
releases:
|
||||
- plucky
|
||||
- oracular
|
||||
- noble
|
@ -0,0 +1,110 @@
|
||||
packages:
|
||||
- name: qt6-base
|
||||
upstream_url: "https://code.qt.io/qt/qtbase.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-base"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-imageformats
|
||||
upstream_url: "https://code.qt.io/qt/qtimageformats.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-imageformats"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-languageserver
|
||||
upstream_url: "https://code.qt.io/qt/qtlanguageserver.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-languageserver"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-shadertools
|
||||
upstream_url: "https://code.qt.io/qt/qtshadertools.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-shadertools"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-svg
|
||||
upstream_url: "https://code.qt.io/qt/qtsvg.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-svg"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-networkauth
|
||||
upstream_url: "https://code.qt.io/qt/qtnetworkauth.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-networkauth"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-serialport
|
||||
upstream_url: "https://code.qt.io/qt/qtserialport.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-serialport"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-declarative
|
||||
upstream_url: "https://code.qt.io/qt/qtdeclarative.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-declarative"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-lottie
|
||||
upstream_url: "https://code.qt.io/qt/qtlottie.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-lottie"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-websockets
|
||||
upstream_url: "https://code.qt.io/qt/qtwebsockets.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-websockets"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-5compat
|
||||
upstream_url: "https://code.qt.io/qt/qt5compat.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-5compat"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-connectivity
|
||||
upstream_url: "https://code.qt.io/qt/qtconnectivity.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-connectivity"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-scxml
|
||||
upstream_url: "https://code.qt.io/qt/qtscxml.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-scxml"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-sensors
|
||||
upstream_url: "https://code.qt.io/qt/qtsensors.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-sensors"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-wayland
|
||||
upstream_url: "https://code.qt.io/qt/qtwayland.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-wayland"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-datavis3d
|
||||
upstream_url: "https://code.qt.io/qt/qtdatavis3d.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-datavis3d"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-grpc
|
||||
upstream_url: "https://code.qt.io/qt/qtgrpc.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-grpc"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-positioning
|
||||
upstream_url: "https://code.qt.io/qt/qtpositioning.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-positioning"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-quicktimeline
|
||||
upstream_url: "https://code.qt.io/qt/qtquicktimeline.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-quicktimeline"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-serialbus
|
||||
upstream_url: "https://code.qt.io/qt/qtserialbus.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-serialbus"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-tools
|
||||
upstream_url: "https://code.qt.io/qt/qttools.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-tools"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-webchannel
|
||||
upstream_url: "https://code.qt.io/qt/qtwebchannel.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-webchannel"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-httpserver
|
||||
upstream_url: "https://code.qt.io/qt/qthttpserver.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-httpserver"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-remoteobjects
|
||||
upstream_url: "https://code.qt.io/qt/qtremoteobjects.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-remoteobjects"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-location
|
||||
upstream_url: "https://code.qt.io/qt/qtlocation.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-location"
|
||||
packaging_branch: "ci/unstable"
|
||||
- name: qt6-translations
|
||||
upstream_url: "https://code.qt.io/qt/qttranslations.git"
|
||||
packaging_url: "https://git.launchpad.net/~ubuntu-qt-code/+git/qt6-translations"
|
||||
packaging_branch: "ci/unstable"
|
||||
|
||||
releases:
|
||||
- plucky
|
||||
- oracular
|
||||
- noble
|
@ -0,0 +1,161 @@
|
||||
#!/bin/bash
|
||||
# download current package indexes to data/<series>{,-proposed}/ for running
|
||||
# britney against a PPA. The PPA will play the role of "-proposed" (i. e.
|
||||
# "unstable" in britney terms, containing the updated packages to test), the
|
||||
# Ubuntu archive has the "-release" part (i. e. "testing" in britney terms, in
|
||||
# which the -proposed packages are being landed).
|
||||
#
|
||||
# Copyright (C) 2019-2024 Simon Quigley <tsimonq2@ubuntu.com>
|
||||
# Copyright (C) Canonical Ltd
|
||||
# Author: Martin Pitt <martin.pitt@ubuntu.com>
|
||||
# Author: Robert Bruce Park <robert.park@canonical.com>
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
set -u
|
||||
|
||||
./pending-packages $RELEASE || exit 0
|
||||
|
||||
export MAIN_ARCHIVE="http://us.archive.ubuntu.com/ubuntu/dists/"
|
||||
export PORTS_ARCHIVE="http://us.ports.ubuntu.com/ubuntu-ports/dists/"
|
||||
export LP_TEAM="lubuntu-ci"
|
||||
export SOURCE_PPA="unstable-ci-proposed"
|
||||
export DEST_PPA="unstable-ci"
|
||||
export SOURCE_PPA_URL="https://ppa.launchpadcontent.net/$LP_TEAM/$SOURCE_PPA/ubuntu/dists/$RELEASE/main";
|
||||
export DEST_PPA_URL="https://ppa.launchpadcontent.net/$LP_TEAM/$DEST_PPA/ubuntu/dists/$RELEASE/main";
|
||||
export ARCHES="amd64"
|
||||
export PORTS_ARCHES="arm64 armhf ppc64el riscv64 s390x"
|
||||
export BRITNEY_CACHE="cache/"
|
||||
export BRITNEY_DATADIR="data/"
|
||||
export BRITNEY_OUTDIR="output/"
|
||||
export BRITNEY_HINTDIR="../hints-ubuntu/"
|
||||
export BRITNEY_LOC="/srv/lubuntu-ci/repos/britney2-ubuntu/britney.py"
|
||||
export BRITNEY_TIMESTAMP=$(date +"%Y-%m-%d_%H:%M:%S")
|
||||
|
||||
echo "Release: $RELEASE";
|
||||
echo "Timestamp: $BRITNEY_TIMESTAMP"
|
||||
|
||||
# Download files in parallel in background, only if there is an update
|
||||
refresh() {
|
||||
DIR=$BRITNEY_CACHE/$pocket/$(echo $1 | rev | cut --delimiter=/ --fields=2,3 | rev)
|
||||
mkdir --parents $DIR
|
||||
touch --no-create $BRITNEY_CACHE $BRITNEY_CACHE/$pocket "$(dirname $DIR)" $DIR # Timestamp thwarts expire.sh
|
||||
wget --directory-prefix $DIR --timestamping $1 --append-output $DIR/$$-wget-log --no-verbose &
|
||||
}
|
||||
|
||||
echo 'Refreshing package indexes...'
|
||||
|
||||
for pocket in $RELEASE $RELEASE-updates; do
|
||||
for component in main restricted universe multiverse; do
|
||||
for arch in $ARCHES; do
|
||||
refresh $MAIN_ARCHIVE/$pocket/$component/binary-$arch/Packages.gz
|
||||
done
|
||||
for arch in $PORTS_ARCHES; do
|
||||
refresh $PORTS_ARCHIVE/$pocket/$component/binary-$arch/Packages.gz
|
||||
done
|
||||
refresh $MAIN_ARCHIVE/$pocket/$component/source/Sources.gz
|
||||
done
|
||||
done
|
||||
|
||||
# Treat the destination PPA as just another pocket
|
||||
for pocket in $RELEASE-ppa-proposed; do
|
||||
for arch in $ARCHES $PORTS_ARCHES; do
|
||||
refresh $DEST_PPA_URL/source/Sources.gz
|
||||
refresh $DEST_PPA_URL/binary-$arch/Packages.gz
|
||||
done
|
||||
done
|
||||
|
||||
# Get the source PPA
|
||||
pocket=$SOURCE_PPA-$RELEASE
|
||||
for arch in $ARCHES $PORTS_ARCHES; do
|
||||
refresh $SOURCE_PPA_URL/binary-$arch/Packages.gz
|
||||
done
|
||||
refresh $SOURCE_PPA_URL/source/Sources.gz
|
||||
|
||||
wait # for wgets to finish
|
||||
|
||||
find $BRITNEY_DATADIR -name "$$-wget-log*" -exec cat '{}' \; -delete 1>&2
|
||||
|
||||
echo 'Building britney indexes...'
|
||||
|
||||
mkdir --parents "$BRITNEY_OUTDIR/$BRITNEY_TIMESTAMP/"
|
||||
|
||||
# "Unstable" is SOURCE_PPA
|
||||
DEST=$BRITNEY_DATADIR/$RELEASE-proposed
|
||||
mkdir --parents $DEST
|
||||
mkdir -pv $BRITNEY_DATADIR/$RELEASE-proposed/state/
|
||||
touch $BRITNEY_DATADIR/$RELEASE-proposed/state/age-policy-dates
|
||||
touch --no-create $DEST
|
||||
ln --verbose --symbolic --force --no-dereference $BRITNEY_HINTDIR $DEST/Hints
|
||||
zcat $BRITNEY_CACHE/$SOURCE_PPA-$RELEASE/*/source/Sources.gz > $DEST/Sources
|
||||
for arch in $ARCHES $PORTS_ARCHES; do
|
||||
zcat $BRITNEY_CACHE/$SOURCE_PPA-$RELEASE/*/binary-$arch/Packages.gz > $DEST/Packages_${arch}
|
||||
done
|
||||
touch $DEST/Blocks $DEST/Dates
|
||||
|
||||
# "Testing" is a combination of the archive and DEST_PPA
|
||||
DEST=$BRITNEY_DATADIR/$RELEASE
|
||||
mkdir --parents $DEST
|
||||
mkdir -pv $BRITNEY_DATADIR/$RELEASE/state/
|
||||
touch $BRITNEY_DATADIR/$RELEASE/state/age-policy-dates
|
||||
touch --no-create $DEST
|
||||
ln --verbose --symbolic --force --no-dereference $BRITNEY_HINTDIR $DEST/Hints
|
||||
zcat $BRITNEY_CACHE/$RELEASE*/*/source/Sources.gz > $DEST/Sources
|
||||
sed -i "s/Section: universe\//Section: /g" $DEST/Sources
|
||||
for arch in $ARCHES $PORTS_ARCHES; do
|
||||
zcat $BRITNEY_CACHE/$RELEASE*/*/binary-$arch/Packages.gz > $DEST/Packages_${arch}
|
||||
sed -i "s/Section: universe\//Section: /g" $DEST/Packages_${arch}
|
||||
done
|
||||
touch $DEST/Blocks
|
||||
touch "$BRITNEY_DATADIR/$SOURCE_PPA-$RELEASE/Dates"
|
||||
|
||||
# Create config file atomically.
|
||||
CONFIG="britney.conf"
|
||||
cp $CONFIG $CONFIG.bak
|
||||
envsubst < "$CONFIG.bak" > "$CONFIG"
|
||||
rm $CONFIG.bak
|
||||
|
||||
echo 'Running britney...'
|
||||
$BRITNEY_LOC -v --config "$CONFIG" --series $RELEASE
|
||||
|
||||
echo 'Syncing output to frontend...'
|
||||
rmdir output/;
|
||||
rsync -da output/ ../../output/britney
|
||||
|
||||
echo "$0 done."
|
||||
|
||||
echo "Moving packages..."
|
||||
|
||||
egrep -v '^#' output/$RELEASE/HeidiResultDelta > candidates || echo "No candidates found.";
|
||||
|
||||
while read -r -a package; do
|
||||
# This only acts on sources; binaries require manual cleanup
|
||||
if [ ${#package[@]} = 2 ]; then
|
||||
COPY="../ubuntu-archive-tools/copy-package"
|
||||
REMOVE="../ubuntu-archive-tools/remove-package"
|
||||
if echo ${package[0]} | egrep -q "^-"; then
|
||||
PACKAGE=$(echo ${package[0]} | sed 's/-//')
|
||||
echo "Demoting $PACKAGE..."
|
||||
$COPY -y -b -s $RELEASE --from "ppa:$LP_TEAM/ubuntu/$DEST_PPA" --to "ppa:$LP_TEAM/ubuntu/$SOURCE_PPA" --version "${package[1]}" "$PACKAGE";
|
||||
$REMOVE -y -s $RELEASE --archive "ppa:$LP_TEAM/ubuntu/$DEST_PPA" --version "${package[1]}" --removal-comment="demoted to proposed" "$PACKAGE";
|
||||
else
|
||||
echo "Migrating ${package[0]}..."
|
||||
$COPY -y -b -s $RELEASE --from "ppa:$LP_TEAM/ubuntu/$SOURCE_PPA" --to "ppa:$LP_TEAM/ubuntu/$DEST_PPA" --version "${package[1]}" "${package[0]}";
|
||||
$REMOVE -y -s $RELEASE --archive "ppa:$LP_TEAM/ubuntu/$SOURCE_PPA" --version "${package[1]}" --removal-comment="moved to release" "${package[0]}";
|
||||
fi
|
||||
fi
|
||||
done < candidates;
|
||||
rm candidates;
|
||||
|
||||
echo "Run the grim reaper..."
|
||||
./grim-reaper
|
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2024 Simon Quigley <tsimonq2@ubuntu.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from datetime import datetime, timedelta
|
||||
from launchpadlib.launchpad import Launchpad
|
||||
|
||||
now = datetime.now()
|
||||
|
||||
def print_log(string):
|
||||
global now
|
||||
old_now = now
|
||||
now = datetime.now()
|
||||
time_elapsed = now - old_now
|
||||
print(f"[{now}] (took {time_elapsed}) {string}")
|
||||
|
||||
print(f"[{now}] Logging into Launchpad...")
|
||||
launchpad = Launchpad.login_with("grim-reaper", "production", version="devel")
|
||||
|
||||
print_log("Logged in. Initializing repositories...")
|
||||
ubuntu = launchpad.distributions["ubuntu"]
|
||||
lubuntu_ci = launchpad.people["lubuntu-ci"]
|
||||
regular = lubuntu_ci.getPPAByName(distribution=ubuntu, name="unstable-ci")
|
||||
proposed = lubuntu_ci.getPPAByName(distribution=ubuntu, name="unstable-ci-proposed")
|
||||
|
||||
print_log("IS THAT THE GRIM REAPER?!?!?!?!!!")
|
||||
|
||||
# Fetch packages once
|
||||
two_weeks_ago = datetime.now() - timedelta(days=14)
|
||||
packages = [proposed.getPublishedSources(status="Superseded"), regular.getPublishedSources(status="Superseded")]
|
||||
total_removals = sum(len(packageset) for packageset in packages)
|
||||
|
||||
print_log(f"Total packages to remove: {total_removals}")
|
||||
current_package = 1
|
||||
current_percentage = 0
|
||||
for packageset in packages:
|
||||
for pkg in packageset:
|
||||
# Cancel all running builds for the package:
|
||||
for build in pkg.getBuilds():
|
||||
if build.buildstate in ["Currently building", "Needs building"]:
|
||||
# Only cancel the build if we can
|
||||
if build.can_be_cancelled:
|
||||
build.cancel()
|
||||
# Delete the source package
|
||||
pkg.requestDeletion(removal_comment="superseded")
|
||||
new_percentage = int(current_package / total_removals)
|
||||
if new_percentage > current_percentage:
|
||||
current_percentage = new_percentage
|
||||
print_log(f"{new_percentage}% complete ({current_package}/{total_removals})")
|
||||
current_package += 1
|
@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2024 Simon Quigley <tsimonq2@ubuntu.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import uuid
|
||||
from common import clean_old_logs
|
||||
from concurrent.futures import ThreadPoolExecutor, wait, FIRST_COMPLETED
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from debian.deb822 import Changes
|
||||
from launchpadlib.launchpad import Launchpad
|
||||
from pathlib import Path
|
||||
|
||||
BASE_OUTPUT_DIR = "/srv/lubuntu-ci/output/"
|
||||
LOG_DIR = os.path.join(BASE_OUTPUT_DIR, "logs/lintian/")
|
||||
|
||||
parser = argparse.ArgumentParser(description="")
|
||||
parser.add_argument("--user", "-u", required=True)
|
||||
parser.add_argument("--ppa", "-p", required=True)
|
||||
parser.add_argument("--ppa2", "-p2")
|
||||
args = parser.parse_args()
|
||||
|
||||
os.makedirs(LOG_DIR, exist_ok=True)
|
||||
current_time = datetime.utcnow().strftime("%H-%M-%S")
|
||||
log_file = os.path.join(LOG_DIR, f"{current_time}.log")
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||
handlers=[
|
||||
logging.FileHandler(log_file)
|
||||
]
|
||||
)
|
||||
logger = logging.getLogger("TimeBasedLogger")
|
||||
|
||||
launchpad = Launchpad.login_with("lintian-ppa", "production", version="devel")
|
||||
ubuntu = launchpad.distributions["ubuntu"]
|
||||
current_series = ubuntu.current_series
|
||||
|
||||
user = launchpad.people[args.user]
|
||||
ppa = user.getPPAByName(distribution=ubuntu, name=args.ppa)
|
||||
if args.ppa2:
|
||||
ppa2 = user.getPPAByName(distribution=ubuntu, name=args.ppa)
|
||||
|
||||
if not os.path.exists(args.user):
|
||||
os.mkdir(args.user)
|
||||
|
||||
lintian = os.path.join(BASE_OUTPUT_DIR, "lintian")
|
||||
lintian_tmp = os.path.join(BASE_OUTPUT_DIR, f".lintian.tmp.{str(uuid.uuid4())[:8]}")
|
||||
if not os.path.exists(lintian):
|
||||
os.mkdir(lintian)
|
||||
if os.path.exists(lintian_tmp):
|
||||
shutil.rmtree(lintian_tmp)
|
||||
os.mkdir(lintian_tmp)
|
||||
|
||||
def rsync(source, destination):
|
||||
src = Path(source)
|
||||
dst = Path(destination)
|
||||
dst.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for item in src.iterdir():
|
||||
src_path = item
|
||||
dst_path = dst / item.name
|
||||
|
||||
if src_path.is_symlink():
|
||||
if dst_path.exists() or dst_path.is_symlink():
|
||||
dst_path.unlink()
|
||||
os.symlink(os.readlink(src_path), dst_path)
|
||||
elif src_path.is_dir():
|
||||
shutil.copytree(src_path, dst_path, symlinks=True, dirs_exist_ok=True)
|
||||
else:
|
||||
shutil.copy2(src_path, dst_path)
|
||||
|
||||
def process_sources(url):
|
||||
tmpdir = os.
|
||||
changes_file = url.split("/")[-1]
|
||||
logging.info(f"Downloading {changes_file} and friends via dget")
|
||||
dget_command = ["dget", "-u", url]
|
||||
result = subprocess.run(dget_command, cwd=tmpdir, capture_output=True)
|
||||
|
||||
with open(os.path.join(tmpdir, changes_file), "r") as f:
|
||||
changes_obj = Changes(f)
|
||||
source = changes_obj["Source"]
|
||||
arch = changes_obj["Architecture"].replace("all", "").replace("_translations", "").split(" ")[0].strip()
|
||||
|
||||
if arch == "":
|
||||
return
|
||||
|
||||
logging.info(f"Running Lintian for {source} on {arch}")
|
||||
lintian_command = ["lintian", "-EvIL", "+pedantic", changes_file]
|
||||
result = subprocess.run(lintian_command, cwd=tmpdir, capture_output=True)
|
||||
stderr = result.stderr.decode("utf-8").strip()
|
||||
stdout = result.stdout.decode("utf-8").strip()
|
||||
|
||||
if stderr == stdout:
|
||||
lintian_output = stderr
|
||||
elif stderr != "" and stdout == "":
|
||||
lintian_output = stderr
|
||||
elif stderr == "" and stdout != "":
|
||||
lintian_output = stdout
|
||||
else:
|
||||
lintian_output = f"{stderr}\n{stdout}"
|
||||
|
||||
output_path = os.path.join(lintian_tmp, source)
|
||||
if not os.path.exists(output_path):
|
||||
os.mkdir(output_path)
|
||||
|
||||
with open(os.path.join(output_path, f"{arch}.txt"), "w") as f:
|
||||
f.write(lintian_output)
|
||||
|
||||
with ThreadPoolExecutor(max_workers=30) as executor:
|
||||
futures = set()
|
||||
|
||||
def main_source_iter():
|
||||
last_run_file = os.path.join(args.user, ".LAST_RUN")
|
||||
last_run_datetime = datetime.now(timezone.utc) - timedelta(days=365)
|
||||
if os.path.exists(last_run_file):
|
||||
with open(last_run_file, "r") as file:
|
||||
last_run_time = file.read().strip()
|
||||
|
||||
last_run_datetime = datetime.fromisoformat(last_run_time)
|
||||
last_run_datetime = last_run_datetime.replace(tzinfo=timezone.utc)
|
||||
logging.info(f"Last run: {last_run_datetime}")
|
||||
|
||||
with open(last_run_file, "w") as file:
|
||||
current_time = datetime.now(timezone.utc).isoformat()
|
||||
file.write(current_time)
|
||||
|
||||
for source in ppa.getPublishedSources(status="Published", distro_series=current_series):
|
||||
for build in source.getBuilds():
|
||||
if build.buildstate == "Successfully built" and build.datebuilt >= last_run_datetime:
|
||||
futures.add(executor.submit(process_sources, build.changesfile_url))
|
||||
|
||||
futures.add(executor.submit(main_source_iter))
|
||||
|
||||
while futures:
|
||||
done, not_done = wait(futures, return_when=FIRST_COMPLETED)
|
||||
|
||||
for future in done:
|
||||
try:
|
||||
result = future.result()
|
||||
except Exception as e:
|
||||
logging.exception("Task generated an exception:")
|
||||
finally:
|
||||
futures.remove(future)
|
||||
|
||||
rsync(lintian_tmp, lintian)
|
||||
shutil.rmtree(lintian_tmp)
|
||||
clean_old_logs(LOG_DIR)
|
||||
logging.info("Done")
|
@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2024 Simon Quigley <tsimonq2@ubuntu.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from launchpadlib.launchpad import Launchpad
|
||||
|
||||
print(f"Logging into Launchpad...")
|
||||
launchpad = Launchpad.login_with("pending-packages", "production", version="devel")
|
||||
|
||||
print("Logged in. Initializing repositories...")
|
||||
ubuntu = launchpad.distributions["ubuntu"]
|
||||
lubuntu_ci = launchpad.people["lubuntu-ci"]
|
||||
regular = lubuntu_ci.getPPAByName(distribution=ubuntu, name="unstable-ci")
|
||||
proposed = lubuntu_ci.getPPAByName(distribution=ubuntu, name="unstable-ci-proposed")
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("release")
|
||||
args = parser.parse_args()
|
||||
series = ubuntu.getSeries(name_or_version=args.release)
|
||||
|
||||
# First, check if any sources are still publishing
|
||||
print("Repositories initialized. Checking for pending sources...")
|
||||
records = [regular.getPublishedSources(status="Pending", distro_series=series),
|
||||
proposed.getPublishedSources(status="Pending", distro_series=series)]
|
||||
total_pending = sum([len(i) for i in records])
|
||||
has_pending = total_pending != 0
|
||||
|
||||
if has_pending:
|
||||
print(f"Total sources pending: {total_pending}")
|
||||
print("Sources are still pending, not running Britney")
|
||||
exit(1)
|
||||
|
||||
# Finally, check if any builds are still running/queued
|
||||
print("No pending sources, continuing. Checking for pending builds...")
|
||||
total_pending = 0
|
||||
total_retried = 0
|
||||
for archive in [proposed, regular]:
|
||||
one_hour_ago = datetime.now(timezone.utc) - timedelta(hours=1)
|
||||
for source in archive.getPublishedSources(status="Published", distro_series=series):
|
||||
for build in source.getBuilds():
|
||||
if build.buildstate == "Currently building":
|
||||
if build.date_started >= one_hour_ago:
|
||||
total_pending += 1
|
||||
elif build.buildstate == "Needs building":
|
||||
total_pending += 1
|
||||
# This isn't technically related, but retry failed builds without logs
|
||||
elif build.buildstate == "Chroot problem" or (build.buildstate == "Failed to build" and not build.build_log_url):
|
||||
if build.can_be_retried:
|
||||
build.retry()
|
||||
total_pending += 1
|
||||
total_retried += 1
|
||||
|
||||
if total_retried != 0:
|
||||
print(f"Total builds retried due to builder flakiness: {total_retried}")
|
||||
|
||||
if total_pending != 0:
|
||||
print(f"Total builds pending: {total_pending}")
|
||||
print("Builds are still running, not running Britney")
|
||||
exit(1)
|
||||
|
||||
print("No pending builds, continuing. Checking for pending binaries...")
|
||||
has_pending = False
|
||||
for pocket in [proposed, regular]:
|
||||
if has_pending:
|
||||
break
|
||||
three_hours_ago = datetime.now(timezone.utc) - timedelta(hours=3)
|
||||
check_builds = set()
|
||||
current_builds = set()
|
||||
source_packages = []
|
||||
|
||||
for build in pocket.getBuildRecords(build_state="Successfully built"):
|
||||
if build.datebuilt < three_hours_ago:
|
||||
del source_packages
|
||||
break
|
||||
check_builds.add(build.title)
|
||||
source_package = build.current_source_publication
|
||||
if source_package and source_package.distro_series == series and source_package not in source_packages:
|
||||
source_packages.append(source_package)
|
||||
for binary in source_package.getPublishedBinaries():
|
||||
current_builds.add(binary.build.title)
|
||||
|
||||
has_pending = not check_builds.issuperset(current_builds) or has_pending
|
||||
|
||||
if has_pending:
|
||||
print("Binaries are still pending, not running Britney")
|
||||
exit(1)
|
||||
|
||||
print("All clear. Starting Britney.")
|
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (C) 2024 Simon Quigley <tsimonq2@ubuntu.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# Configuration
|
||||
LOG_DIR="/srv/lubuntu-ci/output/logs/britney"
|
||||
SCRIPT_PATH="fetch-indexes"
|
||||
MAX_LOG_AGE=86400 # 24 hours in seconds
|
||||
|
||||
# Ensure the log directory exists
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Log rotation: Remove logs older than MAX_LOG_AGE
|
||||
find "$LOG_DIR" -type f -mtime +1 -exec rm -f {} \;
|
||||
|
||||
# Execute the fetch-indexes script for each release and log output
|
||||
for release in plucky oracular noble; do
|
||||
export RELEASE="$release"
|
||||
|
||||
# Log file named by current UTC time (HH-MM-SS)
|
||||
LOG_FILE="$LOG_DIR/$RELEASE_$(date -u +"%H-%M-%S").log"
|
||||
|
||||
echo "$(date -u +"%Y-%m-%d %H:%M:%S") - Running Britney for $RELEASE" >> "$LOG_FILE"
|
||||
"$SCRIPT_PATH" >> "$LOG_FILE" 2>&1
|
||||
done
|
@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=Britney
|
||||
Wants=britney.timer
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=lugito
|
||||
Group=lugito
|
||||
WorkingDirectory=/srv/lubuntu-ci/repos/ci-tools
|
||||
ExecStart=/usr/bin/python3 /srv/lubuntu-ci/repos/ci-tools/run-britney
|
@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Britney timer
|
||||
|
||||
[Timer]
|
||||
OnBootSec=5min
|
||||
OnUnitActiveSec=30min
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
Loading…
Reference in new issue