scriptworker 63.1.0__tar.gz → 63.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scriptworker-63.1.0 → scriptworker-63.2.0}/HISTORY.rst +14 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/PKG-INFO +1 -1
- {scriptworker-63.1.0 → scriptworker-63.2.0}/pyproject.toml +1 -1
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/artifacts.py +23 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/constants.py +12 -1
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/context.py +6 -6
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/cot/verify.py +3 -6
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/log.py +13 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/task.py +3 -2
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/worker.py +18 -2
- {scriptworker-63.1.0 → scriptworker-63.2.0}/.gitignore +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/CONTRIBUTING.rst +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/LICENSE +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/README.rst +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/renovate.json +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/scripts/gen_ed25519_key.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/scriptworker.yaml.tmpl +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/__init__.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/client.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/config.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/cot/__init__.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/cot/generate.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/data/cot_v1_schema.json +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/data/scriptworker_task_schema.json +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/ed25519.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/exceptions.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/github.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/task_process.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/utils.py +0 -0
- {scriptworker-63.1.0 → scriptworker-63.2.0}/tox.ini +0 -0
|
@@ -4,6 +4,20 @@ Change Log
|
|
|
4
4
|
All notable changes to this project will be documented in this file.
|
|
5
5
|
This project adheres to `Semantic Versioning <http://semver.org/>`__.
|
|
6
6
|
|
|
7
|
+
63.2.0 - 2026-06-18
|
|
8
|
+
-------------------
|
|
9
|
+
|
|
10
|
+
Added
|
|
11
|
+
~~~~~
|
|
12
|
+
- When Chain of Trust verification fails, the log is also exposed as public/logs/live_backing.log
|
|
13
|
+
(https://bugzilla.mozilla.org/show_bug.cgi?id=2039779)
|
|
14
|
+
- Values for ESR 153 to scriptworker constants (https://bugzilla.mozilla.org/show_bug.cgi?id=2046216)
|
|
15
|
+
|
|
16
|
+
Fixed
|
|
17
|
+
~~~~~
|
|
18
|
+
- The TASKCLUSTER_CREDENTIALS_FD feature uses a regular temporary file rather than a memfd, to
|
|
19
|
+
make things work again on macOS
|
|
20
|
+
|
|
7
21
|
63.1.0 - 2026-05-26
|
|
8
22
|
-------------------
|
|
9
23
|
|
|
@@ -183,6 +183,29 @@ async def create_artifact(context, path, target_path, content_type, content_enco
|
|
|
183
183
|
raise ScriptWorkerRetryException("Bad status {}".format(resp.status))
|
|
184
184
|
|
|
185
185
|
|
|
186
|
+
async def create_link_artifact(context, target_path, link_to, content_type, expires=None):
|
|
187
|
+
"""Create a Taskcluster link artifact that redirects to another artifact in the same task.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
context (scriptworker.context.Context): the scriptworker context.
|
|
191
|
+
target_path (str): the artifact name to create (e.g., ``public/logs/live_backing.log``).
|
|
192
|
+
link_to (str): the artifact name to link to (e.g., ``public/logs/chain_of_trust.log``).
|
|
193
|
+
content_type (str): Content type (MIME type) of the linked artifact.
|
|
194
|
+
expires (str, optional): ISO datestring of when the artifact expires.
|
|
195
|
+
Defaults to ``context.task["expires"]``.
|
|
196
|
+
|
|
197
|
+
"""
|
|
198
|
+
payload = {
|
|
199
|
+
"storageType": "link",
|
|
200
|
+
"expires": expires or get_expiration_arrow(context).isoformat(),
|
|
201
|
+
"contentType": content_type,
|
|
202
|
+
"artifact": link_to,
|
|
203
|
+
}
|
|
204
|
+
args = [get_task_id(context.claim_task), get_run_id(context.claim_task), target_path, payload]
|
|
205
|
+
log.info("Creating link artifact {} -> {}".format(target_path, link_to))
|
|
206
|
+
await context.temp_queue.createArtifact(*args)
|
|
207
|
+
|
|
208
|
+
|
|
186
209
|
def _craft_artifact_put_headers(content_type, encoding=None):
|
|
187
210
|
log.debug("{} {}".format(content_type, encoding))
|
|
188
211
|
headers = {aiohttp.hdrs.CONTENT_TYPE: content_type}
|
|
@@ -559,6 +559,7 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
559
559
|
"project:releng:lando:repo:release": "release",
|
|
560
560
|
"project:releng:lando:repo:esr115": "esr115",
|
|
561
561
|
"project:releng:lando:repo:esr140": "esr140",
|
|
562
|
+
"project:releng:lando:repo:esr153": "esr153",
|
|
562
563
|
}
|
|
563
564
|
),
|
|
564
565
|
"glean": immutabledict({"project:mozilla:glean:releng:beetmover:bucket:maven-production": "glean-repo"}),
|
|
@@ -645,6 +646,7 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
645
646
|
"/releases/mozilla-release",
|
|
646
647
|
"/releases/mozilla-esr115",
|
|
647
648
|
"/releases/mozilla-esr140",
|
|
649
|
+
"/releases/mozilla-esr153",
|
|
648
650
|
"/projects/birch",
|
|
649
651
|
# Bug 1821839 hneiva using to test hardened signing
|
|
650
652
|
"/projects/maple",
|
|
@@ -654,6 +656,7 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
654
656
|
"/releases/mozilla-release",
|
|
655
657
|
"/releases/mozilla-esr115",
|
|
656
658
|
"/releases/mozilla-esr140",
|
|
659
|
+
"/releases/mozilla-esr153",
|
|
657
660
|
"/projects/birch",
|
|
658
661
|
"/projects/maple",
|
|
659
662
|
"/integration/autoland",
|
|
@@ -667,9 +670,11 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
667
670
|
),
|
|
668
671
|
"esr115": ("/releases/mozilla-esr115",),
|
|
669
672
|
"esr140": ("/releases/mozilla-esr140",),
|
|
673
|
+
"esr153": ("/releases/mozilla-esr153",),
|
|
670
674
|
"esr": (
|
|
671
675
|
"/releases/mozilla-esr115",
|
|
672
676
|
"/releases/mozilla-esr140",
|
|
677
|
+
"/releases/mozilla-esr153",
|
|
673
678
|
),
|
|
674
679
|
"nightly": ("/mozilla-central",),
|
|
675
680
|
"autoland": ("/integration/autoland",),
|
|
@@ -681,6 +686,7 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
681
686
|
"/releases/mozilla-release",
|
|
682
687
|
"/releases/mozilla-esr115",
|
|
683
688
|
"/releases/mozilla-esr140",
|
|
689
|
+
"/releases/mozilla-esr153",
|
|
684
690
|
# bug 1845368: a permanent project branch for testing updates
|
|
685
691
|
"/projects/pine",
|
|
686
692
|
"/projects/larch",
|
|
@@ -693,6 +699,7 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
693
699
|
"/releases/mozilla-release",
|
|
694
700
|
"/releases/mozilla-esr115",
|
|
695
701
|
"/releases/mozilla-esr140",
|
|
702
|
+
"/releases/mozilla-esr153",
|
|
696
703
|
),
|
|
697
704
|
"all-production-branches-and-autoland": (
|
|
698
705
|
"/mozilla-central",
|
|
@@ -700,6 +707,7 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
700
707
|
"/releases/mozilla-release",
|
|
701
708
|
"/releases/mozilla-esr115",
|
|
702
709
|
"/releases/mozilla-esr140",
|
|
710
|
+
"/releases/mozilla-esr153",
|
|
703
711
|
"/integration/autoland",
|
|
704
712
|
),
|
|
705
713
|
}
|
|
@@ -728,6 +736,7 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
728
736
|
"/releases/comm-release",
|
|
729
737
|
"/releases/comm-esr115",
|
|
730
738
|
"/releases/comm-esr140",
|
|
739
|
+
"/releases/comm-esr153",
|
|
731
740
|
),
|
|
732
741
|
"beta": ("/releases/comm-beta",),
|
|
733
742
|
"release": ("/releases/comm-release",),
|
|
@@ -735,14 +744,16 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
735
744
|
"/releases/comm-release",
|
|
736
745
|
"/releases/comm-esr115",
|
|
737
746
|
"/releases/comm-esr140",
|
|
747
|
+
"/releases/comm-esr153",
|
|
738
748
|
),
|
|
739
|
-
"esr": ("/releases/comm-esr115", "/releases/comm-esr140"),
|
|
749
|
+
"esr": ("/releases/comm-esr115", "/releases/comm-esr140", "/releases/comm-esr153"),
|
|
740
750
|
"all-nightly-branches": (
|
|
741
751
|
"/comm-central",
|
|
742
752
|
"/releases/comm-beta",
|
|
743
753
|
"/releases/comm-release",
|
|
744
754
|
"/releases/comm-esr115",
|
|
745
755
|
"/releases/comm-esr140",
|
|
756
|
+
"/releases/comm-esr153",
|
|
746
757
|
),
|
|
747
758
|
"nightly": ("/comm-central",),
|
|
748
759
|
}
|
|
@@ -59,7 +59,7 @@ class Context(object):
|
|
|
59
59
|
|
|
60
60
|
config: Optional[Dict[str, Any]] = None
|
|
61
61
|
credentials_timestamp: Optional[int] = None
|
|
62
|
-
|
|
62
|
+
credentials_file = None
|
|
63
63
|
proc: Optional[task_process.TaskProcess] = None
|
|
64
64
|
queue: Optional[Queue] = None
|
|
65
65
|
session: Optional[aiohttp.ClientSession] = None
|
|
@@ -99,8 +99,7 @@ class Context(object):
|
|
|
99
99
|
if claim_task:
|
|
100
100
|
self.task = claim_task["task"]
|
|
101
101
|
self.verify_task()
|
|
102
|
-
|
|
103
|
-
self.credentials_fd = os.memfd_create("scriptworker_temp_creds", flags=0)
|
|
102
|
+
self.credentials_file = tempfile.TemporaryFile()
|
|
104
103
|
self.temp_credentials = claim_task["credentials"]
|
|
105
104
|
path = os.path.join(self.config["work_dir"], "task.json")
|
|
106
105
|
assert self.task
|
|
@@ -108,8 +107,9 @@ class Context(object):
|
|
|
108
107
|
else:
|
|
109
108
|
self.temp_credentials = None
|
|
110
109
|
self.task = None
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
if self.credentials_file is not None:
|
|
111
|
+
self.credentials_file.close()
|
|
112
|
+
self.credentials_file = None
|
|
113
113
|
|
|
114
114
|
def verify_task(self) -> None:
|
|
115
115
|
"""Run some task sanity checks on ``self.task``."""
|
|
@@ -201,7 +201,7 @@ class Context(object):
|
|
|
201
201
|
if credentials:
|
|
202
202
|
data = json.dumps(credentials, indent=2, sort_keys=True).encode("ascii")
|
|
203
203
|
# use pwrite so we don't confuse the child by changing the file offset
|
|
204
|
-
assert os.pwrite(self.
|
|
204
|
+
assert os.pwrite(self.credentials_file.fileno(), data, 0) == len(data)
|
|
205
205
|
|
|
206
206
|
def write_json(self, path: str, contents: Dict[str, Any], message: str) -> None:
|
|
207
207
|
"""Write json to disk.
|
|
@@ -41,7 +41,7 @@ from scriptworker.context import Context
|
|
|
41
41
|
from scriptworker.ed25519 import ed25519_public_key_from_string, verify_ed25519_signature
|
|
42
42
|
from scriptworker.exceptions import BaseDownloadError, CoTError, ScriptWorkerEd25519Error
|
|
43
43
|
from scriptworker.github import GitHubRepository, extract_github_repo_full_name, extract_github_repo_owner_and_name, extract_github_repo_ssh_url
|
|
44
|
-
from scriptworker.log import contextual_log_handler
|
|
44
|
+
from scriptworker.log import contextual_log_handler, get_chain_of_trust_log_filename
|
|
45
45
|
from scriptworker.task import (
|
|
46
46
|
get_action_callback_name,
|
|
47
47
|
get_and_check_tasks_for,
|
|
@@ -729,10 +729,7 @@ async def download_cot_artifact(chain, task_id, path):
|
|
|
729
729
|
link = chain.get_link(task_id)
|
|
730
730
|
log.debug("Verifying {} is in {} cot artifacts...".format(path, task_id))
|
|
731
731
|
if not link.cot:
|
|
732
|
-
log.warning(
|
|
733
|
-
'Chain of Trust for "{}" in {} does not exist. See above log for more details. \
|
|
734
|
-
Skipping download of this artifact'.format(path, task_id)
|
|
735
|
-
)
|
|
732
|
+
log.warning(f'Chain of Trust for "{path}" in {task_id} does not exist. See above log for more details. Skipping download of this artifact.')
|
|
736
733
|
return
|
|
737
734
|
|
|
738
735
|
if path not in link.cot["artifacts"]:
|
|
@@ -2045,7 +2042,7 @@ async def verify_chain_of_trust(chain, *, check_task=False):
|
|
|
2045
2042
|
CoTError: on failure
|
|
2046
2043
|
|
|
2047
2044
|
"""
|
|
2048
|
-
log_path =
|
|
2045
|
+
log_path = get_chain_of_trust_log_filename(chain.context)
|
|
2049
2046
|
scriptworker_log = logging.getLogger("scriptworker")
|
|
2050
2047
|
with contextual_log_handler(
|
|
2051
2048
|
chain.context,
|
|
@@ -115,6 +115,19 @@ def get_log_filename(context: Any) -> str:
|
|
|
115
115
|
return os.path.join(context.config["task_log_dir"], "live_backing.log")
|
|
116
116
|
|
|
117
117
|
|
|
118
|
+
def get_chain_of_trust_log_filename(context: Any) -> str:
|
|
119
|
+
"""Get the chain of trust verification log file path.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
context (scriptworker.context.Context): the scriptworker context.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
string: chain of trust log file path
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
return os.path.join(context.config["task_log_dir"], "chain_of_trust.log")
|
|
129
|
+
|
|
130
|
+
|
|
118
131
|
@contextmanager
|
|
119
132
|
def get_log_filehandle(context: Any) -> Iterator[IO[str]]:
|
|
120
133
|
"""Open the log and error filehandles.
|
|
@@ -672,7 +672,8 @@ async def run_task(context, to_cancellable_process):
|
|
|
672
672
|
env["TASK_ID"] = context.task_id or "None"
|
|
673
673
|
env["RUN_ID"] = str(get_run_id(context.claim_task))
|
|
674
674
|
env["TASKCLUSTER_ROOT_URL"] = context.config["taskcluster_root_url"]
|
|
675
|
-
|
|
675
|
+
credentials_fd = context.credentials_file.fileno()
|
|
676
|
+
env["TASKCLUSTER_CREDENTIALS_FD"] = str(credentials_fd)
|
|
676
677
|
kwargs = {
|
|
677
678
|
"stdout": PIPE,
|
|
678
679
|
"stderr": PIPE,
|
|
@@ -680,7 +681,7 @@ async def run_task(context, to_cancellable_process):
|
|
|
680
681
|
"close_fds": True,
|
|
681
682
|
"preexec_fn": lambda: os.setsid(),
|
|
682
683
|
"env": env,
|
|
683
|
-
"pass_fds": (
|
|
684
|
+
"pass_fds": (credentials_fd,),
|
|
684
685
|
} # pragma: no branch
|
|
685
686
|
|
|
686
687
|
timeout = get_task_maxruntime(context.task, context.config["task_max_timeout"])
|
|
@@ -8,6 +8,7 @@ Attributes:
|
|
|
8
8
|
|
|
9
9
|
import asyncio
|
|
10
10
|
import logging
|
|
11
|
+
import os
|
|
11
12
|
import signal
|
|
12
13
|
import socket
|
|
13
14
|
import sys
|
|
@@ -17,12 +18,13 @@ from typing import Any
|
|
|
17
18
|
import aiohttp
|
|
18
19
|
import arrow
|
|
19
20
|
|
|
20
|
-
from scriptworker.artifacts import upload_artifacts
|
|
21
|
+
from scriptworker.artifacts import create_link_artifact, upload_artifacts
|
|
21
22
|
from scriptworker.config import get_context_from_cmdln
|
|
22
23
|
from scriptworker.constants import STATUSES
|
|
23
24
|
from scriptworker.cot.generate import generate_cot
|
|
24
25
|
from scriptworker.cot.verify import ChainOfTrust, verify_chain_of_trust
|
|
25
26
|
from scriptworker.exceptions import ScriptWorkerException, WorkerShutdownDuringTask
|
|
27
|
+
from scriptworker.log import get_chain_of_trust_log_filename
|
|
26
28
|
from scriptworker.task import claim_work, complete_task, prepare_to_run_task, reclaim_task, run_task, worst_level
|
|
27
29
|
from scriptworker.task_process import TaskProcess
|
|
28
30
|
from scriptworker.utils import cleanup, filepaths_in_dir, scriptworker_session
|
|
@@ -53,7 +55,21 @@ async def do_run_task(context, run_cancellable, to_cancellable_process):
|
|
|
53
55
|
try:
|
|
54
56
|
if context.config["verify_chain_of_trust"]:
|
|
55
57
|
chain = ChainOfTrust(context, context.config["cot_job_type"])
|
|
56
|
-
|
|
58
|
+
try:
|
|
59
|
+
await run_cancellable(verify_chain_of_trust(chain))
|
|
60
|
+
except Exception:
|
|
61
|
+
# Point live_backing.log at chain_of_trust.log so Treeherder parses the CoT failure
|
|
62
|
+
if os.path.exists(get_chain_of_trust_log_filename(context)):
|
|
63
|
+
try:
|
|
64
|
+
await create_link_artifact(
|
|
65
|
+
context,
|
|
66
|
+
target_path="public/logs/live_backing.log",
|
|
67
|
+
link_to="public/logs/chain_of_trust.log",
|
|
68
|
+
content_type="text/plain",
|
|
69
|
+
)
|
|
70
|
+
except Exception as link_exc:
|
|
71
|
+
log.exception("Failed to create live_backing.log link artifact: {}".format(link_exc))
|
|
72
|
+
raise
|
|
57
73
|
status = await run_task(context, to_cancellable_process)
|
|
58
74
|
generate_cot(context)
|
|
59
75
|
except asyncio.CancelledError:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scriptworker-63.1.0 → scriptworker-63.2.0}/src/scriptworker/data/scriptworker_task_schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|