|
1 | | -# Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. |
| 1 | +# Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. |
2 | 2 | # |
3 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
4 | 4 | # you may not use this file except in compliance with the License. |
@@ -45,6 +45,32 @@ def parse_pkl_project_deps_json(pkl_deps_json_string_path): |
45 | 45 |
|
46 | 46 | return seen_remote_pkl_packages.values() |
47 | 47 |
|
| 48 | +def _eval_pkl_project(ctx, pkl_project_path, extra_args = []): |
| 49 | + """Evaluates a PklProject file as JSON and returns the decoded object. |
| 50 | +
|
| 51 | + Args: |
| 52 | + ctx: A repository context or module context. |
| 53 | + pkl_project_path: Path to the PklProject file to evaluate. |
| 54 | + extra_args: Additional arguments to pass to `pkl eval`. |
| 55 | + Returns: |
| 56 | + The JSON object output of `pkl eval <pkl_project_path> -f json`. |
| 57 | + """ |
| 58 | + if ctx.os.name == "linux" and ctx.os.arch == "amd64": |
| 59 | + pkl_executable = ctx.path(Label("@pkl-cli-linux-amd64//file:downloaded")) |
| 60 | + elif ctx.os.name == "linux" and ctx.os.arch == "aarch64": |
| 61 | + pkl_executable = ctx.path(Label("@pkl-cli-linux-aarch64//file:downloaded")) |
| 62 | + elif ctx.os.name == "mac os x" and ctx.os.arch == "x86_64": |
| 63 | + pkl_executable = ctx.path(Label("@pkl-cli-macos-amd64//file:downloaded")) |
| 64 | + elif ctx.os.name == "mac os x" and ctx.os.arch == "aarch64": |
| 65 | + pkl_executable = ctx.path(Label("@pkl-cli-macos-aarch64//file:downloaded")) |
| 66 | + else: |
| 67 | + fail("Couldn't find pkl executable for os {os} and arch {arch}".format(os = ctx.os.name, arch = ctx.os.arch)) |
| 68 | + |
| 69 | + result = ctx.execute([pkl_executable, "eval", str(pkl_project_path), "--format", "json"] + extra_args) |
| 70 | + if result.return_code != 0: |
| 71 | + fail("Error evaluating PklProject: {}".format(result.stderr)) |
| 72 | + return json.decode(result.stdout) |
| 73 | + |
48 | 74 | def convert_dict_to_options(option_name, items_dict): |
49 | 75 | """Converts the dictioinary to a list with each "key=value" pair preceded by the option name (e.g. --my-option). |
50 | 76 |
|
@@ -72,26 +98,8 @@ def _pkl_project_impl(rctx): |
72 | 98 | rctx.symlink(rctx.attr.pkl_project, "PklProject") |
73 | 99 | rctx.symlink(rctx.path(rctx.attr.pkl_project_deps), "PklProject.deps.json") |
74 | 100 |
|
75 | | - if rctx.os.name == "linux" and rctx.os.arch == "amd64": |
76 | | - pkl_executable = rctx.path(Label("@pkl-cli-linux-amd64//file:downloaded")) |
77 | | - elif rctx.os.name == "linux" and rctx.os.arch == "aarch64": |
78 | | - pkl_executable = rctx.path(Label("@pkl-cli-linux-aarch64//file:downloaded")) |
79 | | - elif rctx.os.name == "mac os x" and rctx.os.arch == "x86_64": |
80 | | - pkl_executable = rctx.path(Label("@pkl-cli-macos-amd64//file:downloaded")) |
81 | | - elif rctx.os.name == "mac os x" and rctx.os.arch == "aarch64": |
82 | | - pkl_executable = rctx.path(Label("@pkl-cli-macos-aarch64//file:downloaded")) |
83 | | - else: |
84 | | - fail("Couldn't find pkl executable for os {os} and arch {arch}".format(os = rctx.os.name, arch = rctx.os.arch)) |
85 | | - |
86 | 101 | env_vars = convert_dict_to_options("--env-var", rctx.attr.environment) |
87 | | - rendered_result = rctx.execute( |
88 | | - ["{}".format(pkl_executable), "eval", "PklProject", "-f", "json"] + env_vars + rctx.attr.extra_flags, |
89 | | - ) |
90 | | - if rendered_result.return_code != 0: |
91 | | - fail("Error evaluating and rendering PklProject file as json: {}".format(rendered_result.stderr)) |
92 | | - metadata = rendered_result.stdout |
93 | | - |
94 | | - pkl_project_metadata = json.decode(metadata) |
| 102 | + pkl_project_metadata = _eval_pkl_project(rctx, "PklProject", extra_args = env_vars + rctx.attr.extra_flags) |
95 | 103 | has_package = "package" in pkl_project_metadata |
96 | 104 |
|
97 | 105 | build_bazel_content = "" |
@@ -129,6 +137,36 @@ pkl_cache( |
129 | 137 |
|
130 | 138 | rctx.file("BUILD.bazel", content = build_bazel_content, executable = False) |
131 | 139 |
|
| 140 | +def _pkl_project_http_rewrites_impl(rctx): |
| 141 | + rules = _eval_pkl_project(rctx, rctx.path(rctx.attr.pkl_project), extra_args = [ |
| 142 | + "--expression", |
| 143 | + # Render the rewrite rules as list, to make sure the order is preserved. |
| 144 | + """ |
| 145 | + new JsonRenderer {} |
| 146 | + .renderValue( |
| 147 | + (evaluatorSettings?.http?.rewrites?.toMap() ?? Map()) |
| 148 | + .entries |
| 149 | + .map( |
| 150 | + (_rule) -> Map(_rule.key, _rule.value) |
| 151 | + ) |
| 152 | + ) |
| 153 | + """, |
| 154 | + ]) |
| 155 | + rctx.file("rules.json", content = json.encode(rules)) |
| 156 | + rctx.file("BUILD.bazel", content = 'exports_files(["rules.json"])\n') |
| 157 | + |
| 158 | +pkl_project_http_rewrites = repository_rule( |
| 159 | + _pkl_project_http_rewrites_impl, |
| 160 | + doc = "Evaluates a PklProject file once to extract HTTP rewrite rules.", |
| 161 | + attrs = { |
| 162 | + "pkl_project": attr.label( |
| 163 | + doc = "The PklProject file to evaluate for HTTP rewrite rules.", |
| 164 | + allow_single_file = True, |
| 165 | + mandatory = True, |
| 166 | + ), |
| 167 | + }, |
| 168 | +) |
| 169 | + |
132 | 170 | pkl_project = repository_rule( |
133 | 171 | _pkl_project_impl, |
134 | 172 | doc = """ |
|
0 commit comments