Skip to content

Commit 3240cdf

Browse files
authored
Merge pull request #272 from nix-community/push-wymqutmrkkuw
feat!: Update output path writing
2 parents 179cb63 + 3dbf4d9 commit 3240cdf

File tree

1 file changed

+56
-6
lines changed

1 file changed

+56
-6
lines changed

buildbot_nix/__init__.py

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -756,16 +756,57 @@ def __init__(self, project: GitProject, path: Path, **kwargs: Any) -> None:
756756
self.project = project
757757
self.path = path
758758

759+
def join_traversalsafe(self, root: Path, joined: Path) -> Path:
760+
root = root.resolve()
761+
762+
for part in joined.parts:
763+
new_root = (root / part).resolve()
764+
765+
if not new_root.is_relative_to(root):
766+
msg = f"Joined path attempted to traverse upwards when processing {root} against {part} (gave {new_root})"
767+
raise ValueError(msg)
768+
769+
root = new_root
770+
771+
return root
772+
773+
def join_all_traversalsafe(self, root: Path, *paths: Path) -> Path:
774+
for path in paths:
775+
root = self.join_traversalsafe(root, path)
776+
777+
return root
778+
779+
@defer.inlineCallbacks
759780
def run(self) -> Generator[Any, object, Any]:
760781
props = self.build.getProperties()
761-
if props.getProperty("branch") != self.project.default_branch:
782+
783+
pr = props.getProperty("pr_number")
784+
785+
if not pr and props.getProperty("branch") != self.project.default_branch:
762786
return util.SKIPPED
763787

764-
attr = Path(props.getProperty("attr")).name
765788
out_path = props.getProperty("out_path")
766-
# XXX don't hardcode this
767-
self.path.mkdir(parents=True, exist_ok=True)
768-
(self.path / attr).write_text(out_path)
789+
790+
if not out_path: # if, e.g., the build fails and doesn't produce an output
791+
return util.SKIPPED
792+
793+
project_name = Path(props.getProperty("projectname"))
794+
795+
target = Path(f"pulls/{pr}") if pr else Path(props.getProperty("branch"))
796+
797+
attr = Path(props.getProperty("attr"))
798+
799+
try:
800+
file = self.join_all_traversalsafe(self.path, project_name, target, attr)
801+
except ValueError as e:
802+
error_log: StreamLog = yield self.addLog("path_error")
803+
error_log.addStderr(f"Path traversal prevented ... skipping update: {e}")
804+
return util.FAILURE
805+
806+
file.parent.mkdir(parents=True, exist_ok=True)
807+
808+
file.write_text(out_path)
809+
769810
return util.SUCCESS
770811

771812

@@ -1074,6 +1115,7 @@ def nix_cached_failure_config(
10741115
def nix_skipped_build_config(
10751116
project: GitProject,
10761117
worker_names: list[str],
1118+
outputs_path: Path | None = None,
10771119
) -> BuilderConfig:
10781120
"""Dummy builder that is triggered when a build is skipped."""
10791121
factory = util.BuildFactory()
@@ -1102,6 +1144,14 @@ def nix_skipped_build_config(
11021144
set_properties={"report_status": False},
11031145
),
11041146
)
1147+
if outputs_path is not None:
1148+
factory.addStep(
1149+
UpdateBuildOutput(
1150+
project=project,
1151+
name="Update build output",
1152+
path=outputs_path,
1153+
),
1154+
)
11051155
return util.BuilderConfig(
11061156
name=f"{project.name}/nix-skipped-build",
11071157
project=project.name,
@@ -1250,7 +1300,7 @@ def config_for_project(
12501300
outputs_path=outputs_path,
12511301
post_build_steps=post_build_steps,
12521302
),
1253-
nix_skipped_build_config(project, [SKIPPED_BUILDER_NAME]),
1303+
nix_skipped_build_config(project, [SKIPPED_BUILDER_NAME], outputs_path),
12541304
nix_failed_eval_config(project, [SKIPPED_BUILDER_NAME]),
12551305
nix_dependency_failed_config(project, [SKIPPED_BUILDER_NAME]),
12561306
nix_cached_failure_config(project, [SKIPPED_BUILDER_NAME]),

0 commit comments

Comments
 (0)