Commit 76547b85 authored by Mustafa Gezen's avatar Mustafa Gezen 🏗
Browse files

Add post-build sigul signing

parent 66751759
......@@ -25,6 +25,12 @@ class Settings(BaseSettings):
# mbs
mbs_url: str
# sigul
sigul_config_file: str = "/etc/distrobuild/sigul.conf"
sigul_passphrase: str
sigul_key_name: str = "signing"
sigul_key_id: str
# oidc
oidc_issuer: str
oidc_client_id: str
......
......@@ -3,6 +3,8 @@ import json
from tortoise import Tortoise
from distrobuild_scheduler.sigul import check_sigul_key
Tortoise.init_models(["distrobuild.models"], "distrobuild")
from distrobuild.settings import TORTOISE_ORM, settings
......@@ -35,19 +37,22 @@ async def consume_messages(i: int):
logger.error("[*] Received unknown message")
async def schedule_periodic_tasks():
def schedule_periodic_tasks():
asyncio.create_task(periodic_tasks.check_build_status())
async def main(loop):
await Tortoise.init(config=TORTOISE_ORM)
await init_channel(loop)
try:
await Tortoise.init(config=TORTOISE_ORM)
await init_channel(loop)
await schedule_periodic_tasks()
await check_sigul_key()
tasks = [consume_messages(i) for i in range(0, settings.workers)]
await asyncio.wait(tasks)
schedule_periodic_tasks()
from distrobuild_scheduler import connection
logger.info("[*] Shutting down")
await connection.close()
tasks = [consume_messages(i) for i in range(0, settings.workers)]
await asyncio.wait(tasks)
finally:
from distrobuild_scheduler import connection
logger.info("[*] Shutting down")
await connection.close()
......@@ -2,53 +2,70 @@ import asyncio
import datetime
import koji
from tortoise.transactions import atomic
from distrobuild.models import Build, BuildStatus, Package
from distrobuild.session import koji_session, mbs_client
from distrobuild.settings import settings
from distrobuild_scheduler import logger
from distrobuild_scheduler.sigul import sign_koji_package
async def check_build_status():
while True:
logger.debug("[*] Running periodic task: check_build_status")
builds = await Build.filter(status=BuildStatus.BUILDING).all()
for build in builds:
if build.koji_id:
task_info = koji_session.getTaskInfo(build.koji_id, request=True)
if task_info["state"] == koji.TASK_STATES["CLOSED"]:
build.status = BuildStatus.SUCCEEDED
await build.save()
@atomic()
async def atomic_check_build_status():
builds = await Build.filter(status=BuildStatus.BUILDING).all()
for build in builds:
if build.koji_id:
task_info = koji_session.getTaskInfo(build.koji_id, request=True)
if task_info["state"] == koji.TASK_STATES["CLOSED"]:
build.status = BuildStatus.SUCCEEDED
await build.save()
package = await Package.filter(id=build.package_id).get()
package.last_build = datetime.datetime.now()
await package.save()
elif task_info["state"] == koji.TASK_STATES["CANCELED"]:
build.status = BuildStatus.CANCELLED
await build.save()
elif task_info["state"] == koji.TASK_STATES["FAILED"]:
try:
task_result = koji_session.getTaskResult(build.koji_id)
print(task_result)
except koji.BuildError:
build.status = BuildStatus.FAILED
except koji.GenericError:
build.status = BuildStatus.CANCELLED
finally:
await build.save()
elif build.mbs_id:
build_info = await mbs_client.get_build(build.mbs_id)
state = build_info["state_name"]
if state == "ready":
build.status = BuildStatus.SUCCEEDED
await build.save()
package = await Package.filter(id=build.package_id).get()
package.last_build = datetime.datetime.now()
await package.save()
package = await Package.filter(id=build.package_id).get()
package.last_build = datetime.datetime.now()
await package.save()
elif state == "failed":
# sign artifacts
build_tasks = koji_session.listBuilds(taskID=build.koji_id)
for build_task in build_tasks:
build_rpms = koji_session.listBuildRPMs(build_task["build_id"])
for rpm in build_rpms:
nvr_arch = "%s.%s" % (rpm["nvr"], rpm["arch"])
await sign_koji_package(nvr_arch)
koji_session.writeSignedRPM(nvr_arch, settings.sigul_key_id)
elif task_info["state"] == koji.TASK_STATES["CANCELED"]:
build.status = BuildStatus.CANCELLED
await build.save()
elif task_info["state"] == koji.TASK_STATES["FAILED"]:
try:
task_result = koji_session.getTaskResult(build.koji_id)
print(task_result)
except koji.BuildError:
build.status = BuildStatus.FAILED
except koji.GenericError:
build.status = BuildStatus.CANCELLED
finally:
await build.save()
elif build.mbs_id:
build_info = await mbs_client.get_build(build.mbs_id)
state = build_info["state_name"]
if state == "ready":
build.status = BuildStatus.SUCCEEDED
await build.save()
package = await Package.filter(id=build.package_id).get()
package.last_build = datetime.datetime.now()
await package.save()
elif state == "failed":
build.status = BuildStatus.FAILED
await build.save()
async def check_build_status():
while True:
logger.debug("[*] Running periodic task: check_build_status")
await atomic_check_build_status()
# run every 5 minutes
await asyncio.sleep(60 * 5)
import asyncio
from typing import List
from distrobuild.settings import settings
from distrobuild_scheduler import logger
class SigulException(Exception):
pass
async def run_sigul(args: List[str]):
args.insert(0, "-c")
args.insert(1, settings.sigul_config_file)
args.insert(2, "--batch")
proc = await asyncio.create_subprocess_exec("sigul",
*args,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
proc.stdin.write(f"{settings.sigul_passphrase}\0".encode())
await proc.wait()
logger.debug('sigul returned with code: %s', proc.returncode)
if proc.returncode != 0:
err = (await proc.stderr.read()).decode()
# means that the package is already signed.
# stupid error
if "ERROR: I/O error: EOFError()" not in err:
raise SigulException(err)
return await proc.communicate()
async def check_sigul_key():
await run_sigul(["get-public-key", settings.sigul_key_name])
async def sign_koji_package(nvr_arch: str):
await run_sigul([
"sign-rpm",
"--koji-only",
"--store-in-koji",
"--v3-signature",
settings.sigul_key_name,
nvr_arch
])
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment