aboutsummaryrefslogtreecommitdiffstats
path: root/sb_builder/jobs.py
diff options
context:
space:
mode:
Diffstat (limited to 'sb_builder/jobs.py')
-rw-r--r--sb_builder/jobs.py63
1 files changed, 58 insertions, 5 deletions
diff --git a/sb_builder/jobs.py b/sb_builder/jobs.py
index bcbd812..b413597 100644
--- a/sb_builder/jobs.py
+++ b/sb_builder/jobs.py
@@ -21,9 +21,9 @@ import re
from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtGui import QFontDatabase, QTextCursor
-from PyQt6.QtWidgets import (QHBoxLayout, QListWidget, QListWidgetItem, QMenu,
- QMessageBox, QPlainTextEdit, QPushButton, QSplitter,
- QToolButton, QVBoxLayout, QWidget)
+from PyQt6.QtWidgets import (QCheckBox, QHBoxLayout, QInputDialog, QLineEdit, QListWidget,
+ QListWidgetItem, QMenu, QMessageBox, QPlainTextEdit, QPushButton,
+ QSplitter, QToolButton, QVBoxLayout, QWidget)
from .fmt import describe
@@ -36,9 +36,10 @@ BAD = ("failed", "killed", "lost")
class JobsTab(QWidget):
refresh_requested = pyqtSignal()
- def __init__(self, remote, parent=None):
+ def __init__(self, remote, publish=True, parent=None):
super().__init__(parent)
self.remote = remote
+ self.pending = ()
self.jobs = {}
self.current = None
self.offset = 0
@@ -52,10 +53,15 @@ class JobsTab(QWidget):
self.apply_btn.clicked.connect(lambda: self.confirm_start(
"Apply the shadowing plan to the repo (sbshadow --yes)?", "sbshadow", "--yes"))
self.apply_btn.hide()
+ self.publish_box = QCheckBox("publish", checked=publish)
+ self.publish_box.setToolTip("Push to the mirror when the build ends; "
+ "unticked, use Publish later")
+ self.run_btn = QPushButton("Run it")
+ self.run_btn.clicked.connect(self.run_preview)
self.kill_btn = QPushButton("Kill")
self.kill_btn.clicked.connect(self.kill)
bar = QHBoxLayout()
- for w in (start, self.apply_btn):
+ for w in (start, self.apply_btn, self.run_btn, self.publish_box):
bar.addWidget(w)
bar.addStretch()
bar.addWidget(self.kill_btn)
@@ -131,6 +137,7 @@ class JobsTab(QWidget):
p.deleteLater()
def start(self, *args):
+ self.pending = args
self.remote.call(self._started, "job-start", *args)
def confirm_start(self, question, *args):
@@ -143,7 +150,49 @@ class JobsTab(QWidget):
self.remote.call(lambda _d, err: err and QMessageBox.warning(self, "Kill failed", err),
"job-kill", self.current)
+ def run_preview(self):
+ """Start the previewed slackrepo run for real."""
+ args = [a for a in self.jobs[self.current]["args"] if a != "--preview"]
+ if not self.publish_box.isChecked():
+ args.insert(1, "--no-publish")
+ self.start_signed("slackrepo", *args)
+
+ def ask_passphrase(self, retry):
+ text, ok = QInputDialog.getText(
+ self, "Signing key", ("Wrong passphrase, try again." if retry else
+ "Passphrase of the package signing key:"),
+ QLineEdit.EchoMode.Password)
+ return text if ok else None
+
+ def start_signed(self, *args, retry=False):
+ """Unlock the signing key first when it is locked, then start the job."""
+ def status(data, err):
+ if err:
+ QMessageBox.warning(self, "Signing key", err)
+ elif data["unlocked"] is False:
+ self._unlock(args, retry)
+ else:
+ self.start(*args)
+ self.remote.call(status, "gpg-status")
+
+ def _unlock(self, args, retry):
+ passphrase = self.ask_passphrase(retry)
+ if passphrase is None:
+ return
+
+ def unlocked(_data, err):
+ if err == "bad passphrase":
+ self._unlock(args, True)
+ elif err:
+ QMessageBox.warning(self, "Signing key", err)
+ else:
+ self.start(*args)
+ self.remote.call(unlocked, "gpg-unlock", stdin=passphrase.encode() + b"\n")
+
def _started(self, data, err):
+ if err == "signing key locked":
+ self.start_signed(*self.pending) # locked since the last check: ask again
+ return
if err:
QMessageBox.warning(self, "Start failed", err)
return
@@ -198,3 +247,7 @@ class JobsTab(QWidget):
self.apply_btn.setVisible(
bool(j) and j["status"] == "ok" and "--no" in j["args"]
and bool(SHADOW_PLAN.search(self.log.toPlainText())))
+ preview = bool(j) and j["kind"] == "slackrepo" and j["status"] == "ok" \
+ and "--preview" in j["args"]
+ self.run_btn.setVisible(preview)
+ self.publish_box.setVisible(preview)