fix(github): expose operator unblock actions
This commit is contained in:
@@ -54,6 +54,7 @@ def build_delivery_closure_workbench(
|
||||
github_summary = _dict(github.get("summary"))
|
||||
github_boundaries = _dict(github.get("operation_boundaries"))
|
||||
github_preflight = _dict(github.get("controlled_execution_preflight"))
|
||||
github_operator_unblock = _dict(github_preflight.get("operator_unblock"))
|
||||
gitea_status = _dict(gitea.get("program_status"))
|
||||
gitea_rollups = _dict(gitea.get("rollups"))
|
||||
runtime_status = _dict(runtime.get("program_status"))
|
||||
@@ -123,7 +124,14 @@ def build_delivery_closure_workbench(
|
||||
is True,
|
||||
},
|
||||
"href": "/governance?tab=automation-inventory",
|
||||
"operator_unblock": github_operator_unblock,
|
||||
"next_action": str(
|
||||
_first_string(github_operator_unblock.get("required_actions"))
|
||||
or github_operator_unblock.get("safe_handoff")
|
||||
or github_preflight.get("operator_unblock_status")
|
||||
or ""
|
||||
)
|
||||
or str(
|
||||
_first_target_action(github_preflight.get("targets"))
|
||||
or github.get("next_action")
|
||||
or _first_target_action(github.get("targets"))
|
||||
@@ -241,9 +249,7 @@ def build_delivery_closure_workbench(
|
||||
"github_account_status": str(
|
||||
github_preflight.get("github_account_status") or "unknown"
|
||||
),
|
||||
"github_account_suspended": github_preflight.get(
|
||||
"github_account_suspended"
|
||||
)
|
||||
"github_account_suspended": github_preflight.get("github_account_suspended")
|
||||
is True,
|
||||
"github_api_forbidden_count": _int(
|
||||
github_preflight.get("github_api_forbidden_count")
|
||||
@@ -252,6 +258,11 @@ def build_delivery_closure_workbench(
|
||||
github_preflight.get("controlled_apply_ready_count")
|
||||
),
|
||||
"github_blocked_preflight_target_count": github_preflight_blockers,
|
||||
"github_operator_unblock_required": github_operator_unblock.get("required")
|
||||
is True,
|
||||
"github_operator_unblock_status": str(
|
||||
github_operator_unblock.get("status") or ""
|
||||
),
|
||||
"secret_values_collected": False,
|
||||
},
|
||||
"source_statuses": source_statuses,
|
||||
|
||||
@@ -35,6 +35,20 @@ _EXECUTION_AUTHORIZATION_SCHEMA_VERSION = (
|
||||
_CONTROLLED_EXECUTION_PREFLIGHT_SCHEMA_VERSION = (
|
||||
"github_target_controlled_execution_preflight_v1"
|
||||
)
|
||||
_GITHUB_WRITE_CHANNEL_RECHECK_COMMANDS = [
|
||||
"gh api /user --jq '{login:.login}'",
|
||||
"git push --dry-run origin HEAD:refs/heads/codex-github-write-channel-readonly-check",
|
||||
]
|
||||
_GITHUB_OPERATOR_UNBLOCK_ACTIONS = [
|
||||
"complete_github_account_suspension_appeal_or_provide_authorized_writable_namespace",
|
||||
"refresh_local_github_cli_login_without_sharing_tokens_or_cookies",
|
||||
"rerun_github_write_channel_dry_run_before_create_or_refs_sync",
|
||||
]
|
||||
_GITHUB_OPERATOR_STILL_FORBIDDEN = [
|
||||
"do_not_paste_pat_token_private_key_cookie_session_or_authorization_header",
|
||||
"do_not_collect_private_clone_url_or_credential_value",
|
||||
"do_not_force_push_delete_refs_or_change_public_visibility",
|
||||
]
|
||||
_PREFLIGHT_SCHEMA_VERSION = "github_target_owner_response_intake_preflight_v1"
|
||||
_PREFLIGHT_MODE = "validate_owner_response_only_no_persist_no_github_write"
|
||||
_SAFE_CREDENTIAL_REVIEW_SCHEMA_VERSION = (
|
||||
@@ -2092,6 +2106,9 @@ def _controlled_execution_preflight_readiness(
|
||||
create_channel_ready = summary.get("github_create_repo_channel_ready") is True
|
||||
refs_channel_ready = summary.get("github_refs_sync_channel_ready") is True
|
||||
write_channel_ready = create_channel_ready and refs_channel_ready
|
||||
github_account_status = str(summary.get("github_account_status") or "unknown")
|
||||
github_account_suspended = summary.get("github_account_suspended") is True
|
||||
github_api_forbidden_count = _int(summary.get("github_api_forbidden_count"))
|
||||
preflight_ready = (
|
||||
bool(preflight_targets)
|
||||
and authorization_summary["authorization_present"] is True
|
||||
@@ -2110,6 +2127,12 @@ def _controlled_execution_preflight_readiness(
|
||||
for row in preflight_targets
|
||||
if row.get("github_repo")
|
||||
}
|
||||
operator_unblock = _github_write_channel_operator_unblock(
|
||||
github_account_status=github_account_status,
|
||||
github_account_suspended=github_account_suspended,
|
||||
github_api_forbidden_count=github_api_forbidden_count,
|
||||
github_write_channel_ready=write_channel_ready,
|
||||
)
|
||||
return {
|
||||
"schema_version": str(
|
||||
payload.get("schema_version")
|
||||
@@ -2129,9 +2152,9 @@ def _controlled_execution_preflight_readiness(
|
||||
and authorization_summary["repo_creation_authorized"] is True
|
||||
and authorization_summary["refs_sync_authorized"] is True,
|
||||
"github_write_channel_ready": write_channel_ready,
|
||||
"github_account_status": str(summary.get("github_account_status") or "unknown"),
|
||||
"github_account_suspended": summary.get("github_account_suspended") is True,
|
||||
"github_api_forbidden_count": _int(summary.get("github_api_forbidden_count")),
|
||||
"github_account_status": github_account_status,
|
||||
"github_account_suspended": github_account_suspended,
|
||||
"github_api_forbidden_count": github_api_forbidden_count,
|
||||
"github_create_repo_channel_ready": create_channel_ready,
|
||||
"github_refs_sync_channel_ready": refs_channel_ready,
|
||||
"github_connector_repo_creation_tool_available": summary.get(
|
||||
@@ -2161,6 +2184,9 @@ def _controlled_execution_preflight_readiness(
|
||||
"required_preflight_checks": _strings(payload.get("required_preflight_checks")),
|
||||
"rollback_plan": _dict(payload.get("rollback_plan")),
|
||||
"post_apply_verifiers": _strings(payload.get("post_apply_verifiers")),
|
||||
"operator_unblock_required": operator_unblock["required"],
|
||||
"operator_unblock_status": operator_unblock["status"],
|
||||
"operator_unblock": operator_unblock,
|
||||
"operation_boundaries": {
|
||||
"read_only_api_allowed": boundaries.get("read_only_api_allowed") is True,
|
||||
"github_api_write_allowed_by_authorization": boundaries.get(
|
||||
@@ -2187,6 +2213,40 @@ def _controlled_execution_preflight_readiness(
|
||||
}
|
||||
|
||||
|
||||
def _github_write_channel_operator_unblock(
|
||||
*,
|
||||
github_account_status: str,
|
||||
github_account_suspended: bool,
|
||||
github_api_forbidden_count: int,
|
||||
github_write_channel_ready: bool,
|
||||
) -> dict[str, Any]:
|
||||
required = not github_write_channel_ready
|
||||
if github_account_suspended:
|
||||
status = "github_account_suspended_external_action_required"
|
||||
elif required:
|
||||
status = "github_write_channel_reauthentication_or_namespace_required"
|
||||
else:
|
||||
status = "github_write_channel_ready_no_operator_action"
|
||||
|
||||
return {
|
||||
"required": required,
|
||||
"status": status,
|
||||
"github_account_status": github_account_status,
|
||||
"github_account_suspended": github_account_suspended,
|
||||
"github_api_forbidden_count": github_api_forbidden_count,
|
||||
"required_actions": _GITHUB_OPERATOR_UNBLOCK_ACTIONS if required else [],
|
||||
"recheck_commands": _GITHUB_WRITE_CHANNEL_RECHECK_COMMANDS if required else [],
|
||||
"still_forbidden": _GITHUB_OPERATOR_STILL_FORBIDDEN,
|
||||
"safe_handoff": (
|
||||
"GitHub owner must restore the suspended account or provide a writable "
|
||||
"private GitHub namespace. Do not share tokens, cookies, private keys, "
|
||||
"authorization headers, or private clone URLs."
|
||||
)
|
||||
if required
|
||||
else "GitHub write channel is ready for controlled apply preflight.",
|
||||
}
|
||||
|
||||
|
||||
def _controlled_execution_target_summary(value: Any) -> dict[str, Any]:
|
||||
row = _dict(value)
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user