#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # SPDX-FileCopyrightText: 2023 KDE e.V. # SPDX-FileContributor: Ingo Klöcker import logging import os import sys from pathlib import Path from typing import Optional from sftpnotary import config, projects, util from sftpnotary.exceptions import Error from sftpnotary.flatpaksigner import getRefFromFlatpakBundle, SignFlatpakJob log = logging.getLogger("signflatpak") def parseCommandLine(): import argparse parser = argparse.ArgumentParser(description="Sign Flatpak bundle with signing service and publish it in a repo") # debug options parser.add_argument("-v", "--verbose", action="count", default=0, help="increase the verbosity") parser.add_argument("--config", required=True) parser.add_argument( "--debug-bundle", type=Path, dest="debugBundle", help="the .flatpak bundle with the debug symbols" ) parser.add_argument( "--locale-bundle", type=Path, dest="localeBundle", help="the .flatpak bundle with the translations" ) parser.add_argument("flatpak", type=Path, help="the .flatpak bundle to sign") options = parser.parse_args() return options def logTaskLog(logFile: Path): log.info("Logs of remote signing:") with open(logFile, "r", encoding="utf-8") as f: for line in f: log.info(line.rstrip()) def signFlatpak( flatpak: Path, localeBundle: Optional[Path], debugBundle: Optional[Path], projectPath: str, branch: str ) -> bool: log.debug(f"Flatpak ref of {flatpak}: {getRefFromFlatpakBundle(flatpak)}") if localeBundle: log.debug(f"Flatpak ref of {localeBundle}: {getRefFromFlatpakBundle(localeBundle)}") if debugBundle: log.debug(f"Flatpak ref of {debugBundle}: {getRefFromFlatpakBundle(debugBundle)}") with util.connectToSftpServer() as sftp: job = SignFlatpakJob( sftp, flatpakFilePath=flatpak, localeBundlePath=localeBundle, debugBundlePath=debugBundle, token=os.environ.get("CI_JOB_TOKEN"), projectPath=projectPath, branch=branch, ) try: job.start() job.waitForCompletion() except Exception as e: # or more specific exception log.error("Error: SignFlatpakJob failed", exc_info=e) for logFile in job.logFiles: if logFile.name == "task.log": logTaskLog(logFile) if not job.success: log.error("Error: Signing Flatpak bundle failed") return job.success def main() -> int: options = parseCommandLine() config.loadConfig(options.config) util.setUpClientLogging(log, options.verbose) projectSettingsLocation = config.settings.get("General", "ProjectSettings", "flatpaksigner-projects.yaml") util.loadProjectSettings( projectSettingsLocation, relativeTo=Path(options.config).absolute().parent, ) # Ignore merge request pipelines if os.environ.get("CI_PIPELINE_SOURCE") == "merge_request_event": log.info("Merge request pipelines are not cleared for signing. Skipping.") return 0 # Check if it makes sense to attempt signing the flatpak projectPath = os.environ["CI_PROJECT_PATH"] branch = os.environ["CI_COMMIT_REF_NAME"] if not projects.settings.exists(projectPath, branch): log.info( f"""Branch '{branch}' of project '{projectPath}' is not cleared for signing flatpaks. Skipping.\n You can clear it by adding the branch to {projectSettingsLocation}""" ) return 0 success = signFlatpak(options.flatpak, options.localeBundle, options.debugBundle, projectPath, branch) return 0 if success else 1 if __name__ == "__main__": try: sys.exit(main()) except Error as e: print("Error: %s" % e, file=sys.stderr) sys.exit(1)