Merge pull request #80 from living-ip/codex/gcp-iap-failure-receipt
Some checks are pending
CI / lint-and-test (push) Waiting to run
Some checks are pending
CI / lint-and-test (push) Waiting to run
Retain sanitized GCP operator failure receipts
This commit is contained in:
commit
206ea51951
2 changed files with 64 additions and 0 deletions
47
.github/workflows/gcp-iap-operator.yml
vendored
47
.github/workflows/gcp-iap-operator.yml
vendored
|
|
@ -179,11 +179,13 @@ jobs:
|
|||
export_environment_variables: true
|
||||
|
||||
- name: Install Google Cloud CLI
|
||||
id: setup_gcloud
|
||||
uses: google-github-actions/setup-gcloud@v3
|
||||
with:
|
||||
project_id: ${{ env.PROJECT_ID }}
|
||||
|
||||
- name: Run fixed IAP operation
|
||||
id: operate
|
||||
shell: bash
|
||||
env:
|
||||
OPERATION: ${{ inputs.operation }}
|
||||
|
|
@ -193,6 +195,51 @@ jobs:
|
|||
set -euo pipefail
|
||||
scripts/gcp_iap_operator.sh "${OPERATION}" "${REQUEST_ID}" "${TARGET_DB}"
|
||||
|
||||
- name: Ensure sanitized result receipt
|
||||
if: always()
|
||||
shell: bash
|
||||
env:
|
||||
OPERATION: ${{ inputs.operation }}
|
||||
REQUEST_ID: ${{ inputs.request_id }}
|
||||
TARGET_DB: ${{ inputs.target_db }}
|
||||
VALIDATE_OUTCOME: ${{ steps.validate.outcome }}
|
||||
AUTH_OUTCOME: ${{ steps.auth.outcome }}
|
||||
SETUP_GCLOUD_OUTCOME: ${{ steps.setup_gcloud.outcome }}
|
||||
OPERATE_OUTCOME: ${{ steps.operate.outcome }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
install -d -m 0700 "${RESULT_DIR}"
|
||||
result_path="${RESULT_DIR}/result.json"
|
||||
if [[ -s "${result_path}" ]] && python3 -c 'import json,sys; json.load(open(sys.argv[1]))' "${result_path}"; then
|
||||
exit 0
|
||||
fi
|
||||
RESULT_PATH="${result_path}" python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
result = {
|
||||
"schema": "livingip.gcpIapOperatorResult.v1",
|
||||
"operation": os.environ["OPERATION"],
|
||||
"request_id": os.environ["REQUEST_ID"],
|
||||
"target_db": os.environ["TARGET_DB"],
|
||||
"status": "fail",
|
||||
"failure_class": "workflow_stopped_before_valid_operator_result",
|
||||
"step_outcomes": {
|
||||
"validate": os.environ["VALIDATE_OUTCOME"],
|
||||
"auth": os.environ["AUTH_OUTCOME"],
|
||||
"setup_gcloud": os.environ["SETUP_GCLOUD_OUTCOME"],
|
||||
"operate": os.environ["OPERATE_OUTCOME"],
|
||||
},
|
||||
"credential_values_logged": False,
|
||||
"raw_stdout_retained": False,
|
||||
"raw_stderr_retained": False,
|
||||
}
|
||||
path = Path(os.environ["RESULT_PATH"])
|
||||
path.write_text(json.dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||
path.chmod(0o600)
|
||||
PY
|
||||
|
||||
- name: Upload sanitized result
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
|
|||
|
|
@ -153,6 +153,23 @@ def test_workflow_initializes_runner_paths_at_step_runtime() -> None:
|
|||
assert "runner.temp" not in WORKFLOW.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_workflow_retains_sanitized_failure_receipt_before_upload() -> None:
|
||||
workflow = load_workflow()
|
||||
steps = workflow["jobs"]["operate"]["steps"]
|
||||
receipt_index = next(i for i, step in enumerate(steps) if step.get("name") == "Ensure sanitized result receipt")
|
||||
upload_index = next(i for i, step in enumerate(steps) if step.get("uses") == "actions/upload-artifact@v4")
|
||||
receipt = steps[receipt_index]
|
||||
source = receipt["run"]
|
||||
assert receipt_index < upload_index
|
||||
assert receipt["if"] == "always()"
|
||||
assert receipt["env"]["AUTH_OUTCOME"] == "${{ steps.auth.outcome }}"
|
||||
assert receipt["env"]["OPERATE_OUTCOME"] == "${{ steps.operate.outcome }}"
|
||||
assert "workflow_stopped_before_valid_operator_result" in source
|
||||
assert '"credential_values_logged": False' in source
|
||||
assert '"raw_stdout_retained": False' in source
|
||||
assert '"raw_stderr_retained": False' in source
|
||||
|
||||
|
||||
def test_workflow_builds_exact_main_bundle_from_tracked_files_and_hashes() -> None:
|
||||
source = WORKFLOW.read_text(encoding="utf-8")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue