Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions scripts/runtime_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,17 @@ class Assignment:
name: str
value: str

@property
def deletes_variable(self) -> bool:
return self.value == ""

def gh_command(self, *, redact_body: bool = False, redact_metadata: bool = False) -> list[str]:
body = redacted_value() if redact_body else self.value
repository = redacted_value() if redact_metadata else self.repository
command = ["gh", "variable", "set", self.name, "--repo", repository, "--body", body]
if self.deletes_variable:
command = ["gh", "variable", "delete", self.name, "--repo", repository]
else:
body = redacted_value() if redact_body else self.value
command = ["gh", "variable", "set", self.name, "--repo", repository, "--body", body]
if self.variable_scope == "environment":
environment = redacted_value() if redact_metadata else (self.environment or "")
command.extend(["--env", environment])
Expand All @@ -91,6 +98,7 @@ def assignment_payload(assignment: Assignment, *, redact_values: bool = False) -
"variable_scope": assignment.variable_scope,
"environment": assignment.environment,
"name": assignment.name,
"action": "delete" if assignment.deletes_variable else "set",
"value": redacted_value() if redact_values else assignment.value,
}
if redact_values:
Expand Down Expand Up @@ -570,7 +578,24 @@ def command_apply(args: argparse.Namespace) -> int:
return 0

for assignment in all_assignments:
subprocess.run(assignment.gh_command(), check=True)
result = subprocess.run(
assignment.gh_command(),
text=True,
capture_output=assignment.deletes_variable,
check=False,
)
if result.returncode == 0:
continue
if assignment.deletes_variable:
detail = f"{result.stderr}\n{result.stdout}".lower()
if "not found" in detail or "could not find" in detail or "http 404" in detail:
print(f"{assignment.name} was already absent; delete skipped.")
continue
if result.stderr:
print(result.stderr, file=sys.stderr, end="")
if result.stdout:
print(result.stdout, file=sys.stderr, end="")
raise subprocess.CalledProcessError(result.returncode, assignment.gh_command())
return 0


Expand Down
27 changes: 27 additions & 0 deletions tests/test_runtime_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,33 @@ def test_assignment_shell_command_can_redact_body_and_metadata(self):
self.assertNotIn(assignment.repository, command)
self.assertNotIn(assignment.environment, command)

def test_empty_assignment_deletes_variable_instead_of_setting_empty_body(self):
assignment = runtime_settings.Assignment(
"longbridge/sg",
"QuantStrategyLab/LongBridgePlatform",
"environment",
"longbridge-sg",
"LONGBRIDGE_MIN_RESERVED_CASH_USD",
"",
)

self.assertTrue(assignment.deletes_variable)
self.assertEqual(
assignment.gh_command(),
[
"gh",
"variable",
"delete",
"LONGBRIDGE_MIN_RESERVED_CASH_USD",
"--repo",
"QuantStrategyLab/LongBridgePlatform",
"--env",
"longbridge-sg",
],
)
self.assertNotIn("--body", assignment.shell_command())
self.assertEqual(runtime_settings.assignment_payload(assignment)["action"], "delete")

def test_plugin_mount_schema_version_must_be_non_empty_string(self):
_, target = self.load_target("examples/targets/schwab/live.example.json")
target["plugin_mounts"][0]["expected_schema_version"] = ""
Expand Down