OpenMiInk/third_party/ci-notary-service/publishwebsite.py
Hellings b8c8ff98e2 Hi
2026-10-16 09:05:56 -04:00

120 lines
4 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: BSD-2-Clause
#
# SPDX-FileCopyrightText: 2023 KDE e.V.
# SPDX-FileCopyrightText: 2023 Ben Cooksley <bcooksley@kde.org>
# SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
import logging
import os
import sys
import tarfile
from pathlib import Path
from tempfile import NamedTemporaryFile
from sftpnotary import config, projects, util
from sftpnotary.exceptions import Error
from sftpnotary.websitepublisher import PublishWebsiteJob
log = logging.getLogger("publishwebsite")
def parseCommandLine():
import argparse
parser = argparse.ArgumentParser(description="Publish files via RSync to a remote server (usually a web server)")
# debug options
parser.add_argument("-v", "--verbose", action="count", default=0, help="increase the verbosity")
parser.add_argument("--config", required=True, help="the configuration to use; required")
parser.add_argument("folderToPublish", help="the folder to be published to the remote server; required")
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 publishWebsite(websiteArchiveFilePath: Path, projectPath: str, branch: str) -> bool:
with util.connectToSftpServer() as sftp:
job = PublishWebsiteJob(
sftp,
websiteArchiveFilePath=websiteArchiveFilePath,
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: PublishWebsiteJob failed", exc_info=e)
for logFile in job.logFiles:
if logFile.name == "task.log":
logTaskLog(logFile)
if not job.success:
log.error("Error: Publishing the website failed")
return job.success
def main() -> int:
options = parseCommandLine()
config.loadConfig(options.config)
util.setUpClientLogging(log, options.verbose)
projectSettingsLocation = config.settings.get("General", "ProjectSettings", "websitepublisher-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 publishing. Skipping.")
return 0
# Check if it makes sense to attempt publishing the website
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 publishing. Skipping.\n
You can clear it by adding the branch to {projectSettingsLocation}"""
)
return 0
# Build a tarball of the website files and trigger the publishing process
with NamedTemporaryFile() as websiteArchive:
# Open our temporary file as a tarball
archive = tarfile.open(fileobj=websiteArchive, mode="w")
# Determine the path to be archived and the files to be included
pathToArchive = Path(options.folderToPublish)
filesToInclude = os.listdir(pathToArchive)
# Start populating it with the website files
for filename in filesToInclude:
fullPath = pathToArchive / filename
archive.add(fullPath, arcname=filename, recursive=True)
# Close it out to ensure everything is flushed to disk
archive.close()
websiteArchive.flush()
success = publishWebsite(Path(websiteArchive.name), 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)