203 lines
8 KiB
YAML
203 lines
8 KiB
YAML
name: gcp-iap-operator
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
operation:
|
|
description: Fixed reviewed operation
|
|
required: true
|
|
type: choice
|
|
options:
|
|
- status
|
|
- direct-claim-replay
|
|
- cleanup-clone
|
|
request_id:
|
|
description: iap- followed by 12-32 lowercase letters or digits
|
|
required: true
|
|
type: string
|
|
target_db:
|
|
description: teleo_clone_status for status, otherwise the exact generated clone database
|
|
required: true
|
|
default: teleo_clone_status
|
|
type: string
|
|
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
|
|
concurrency:
|
|
group: gcp-iap-operator-${{ github.run_id }}
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
PROJECT_ID: teleo-501523
|
|
WORKLOAD_IDENTITY_PROVIDER: projects/785938879453/locations/global/workloadIdentityPools/github-actions/providers/teleo-iap-operator
|
|
STATUS_SERVICE_ACCOUNT: sa-teleo-iap-status@teleo-501523.iam.gserviceaccount.com
|
|
CLONE_SERVICE_ACCOUNT: sa-teleo-iap-clone-operator@teleo-501523.iam.gserviceaccount.com
|
|
EXPECTED_WORKFLOW_REF: living-ip/teleo-infrastructure/.github/workflows/gcp-iap-operator.yml@refs/heads/main
|
|
DISPATCHER_VERSION: teleo-gcp-iap-operator-v1
|
|
|
|
jobs:
|
|
operate:
|
|
name: Fixed IAP operator command
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
steps:
|
|
- name: Check out the dispatched main revision
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Initialize runner-local paths
|
|
id: paths
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
[[ -n "${RUNNER_TEMP:-}" ]] || exit 2
|
|
printf 'BUNDLE_DIR=%s\n' "${RUNNER_TEMP}/gcp-iap-operator-bundle" >> "${GITHUB_ENV}"
|
|
printf 'RESULT_DIR=%s\n' "${RUNNER_TEMP}/gcp-iap-operator-result" >> "${GITHUB_ENV}"
|
|
|
|
- name: Validate fixed inputs and select identity
|
|
id: validate
|
|
shell: bash
|
|
env:
|
|
OPERATION: ${{ inputs.operation }}
|
|
REQUEST_ID: ${{ inputs.request_id }}
|
|
TARGET_DB: ${{ inputs.target_db }}
|
|
run: |
|
|
set -euo pipefail
|
|
[[ "${GITHUB_REF}" == "refs/heads/main" ]] || exit 2
|
|
[[ "${GITHUB_WORKFLOW_REF}" == "${EXPECTED_WORKFLOW_REF}" ]] || exit 2
|
|
request_id_re='^iap-[a-z0-9]{12,32}$'
|
|
target_db_re='^teleo_clone_[a-z0-9][a-z0-9_]{0,50}$'
|
|
[[ "${REQUEST_ID}" =~ ${request_id_re} ]] || exit 2
|
|
[[ "${TARGET_DB}" =~ ${target_db_re} ]] || exit 2
|
|
case "${OPERATION}" in
|
|
status)
|
|
[[ "${TARGET_DB}" == "teleo_clone_status" ]] || exit 2
|
|
service_account="${STATUS_SERVICE_ACCOUNT}"
|
|
;;
|
|
direct-claim-replay|cleanup-clone)
|
|
[[ "${TARGET_DB}" != "teleo_clone_status" ]] || exit 2
|
|
service_account="${CLONE_SERVICE_ACCOUNT}"
|
|
;;
|
|
*) exit 2 ;;
|
|
esac
|
|
printf 'service_account=%s\n' "${service_account}" >> "${GITHUB_OUTPUT}"
|
|
install -d -m 0700 "${RESULT_DIR}"
|
|
: > "${RESULT_DIR}/result.json"
|
|
chmod 0600 "${RESULT_DIR}/result.json"
|
|
|
|
- name: Build strict reviewed operation bundle
|
|
if: ${{ inputs.operation != 'status' }}
|
|
shell: bash
|
|
env:
|
|
OPERATION: ${{ inputs.operation }}
|
|
REQUEST_ID: ${{ inputs.request_id }}
|
|
TARGET_DB: ${{ inputs.target_db }}
|
|
run: |
|
|
set -euo pipefail
|
|
python3 - <<'PY'
|
|
import gzip
|
|
import hashlib
|
|
import io
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import tarfile
|
|
from pathlib import Path
|
|
|
|
root = Path.cwd().resolve()
|
|
operation = os.environ["OPERATION"]
|
|
request_id = os.environ["REQUEST_ID"]
|
|
target_db = os.environ["TARGET_DB"]
|
|
common = ["scripts/gcp_iap_operator.sh"]
|
|
direct_claim = [
|
|
"scripts/run_gcp_generated_db_direct_claim_suite.py",
|
|
"scripts/run_leo_clone_bound_handler_checkpoint.py",
|
|
"scripts/working_leo_open_ended_benchmark.py",
|
|
"hermes-agent/leoclean-bin/cloudsql_memory_tool.py",
|
|
"ops/postgres_parity_manifest.sql",
|
|
f"docs/reports/leo-working-state-20260709/{target_db}-canonical-parity-receipt.json",
|
|
]
|
|
allowed = common + (direct_claim if operation == "direct-claim-replay" else [])
|
|
if operation not in {"direct-claim-replay", "cleanup-clone"}:
|
|
raise SystemExit("bundle requested for a non-clone operation")
|
|
head = subprocess.check_output(["git", "rev-parse", "HEAD"], text=True).strip()
|
|
if head != os.environ["GITHUB_SHA"]:
|
|
raise SystemExit("checkout HEAD does not match GITHUB_SHA")
|
|
files = {}
|
|
payloads = {}
|
|
for relative in allowed:
|
|
subprocess.run(
|
|
["git", "ls-files", "--error-unmatch", "--", relative],
|
|
check=True,
|
|
stdout=subprocess.DEVNULL,
|
|
)
|
|
path = root / relative
|
|
if not path.is_file() or path.is_symlink() or root not in path.resolve().parents:
|
|
raise SystemExit(f"unsafe or missing tracked bundle file: {relative}")
|
|
data = path.read_bytes()
|
|
payloads[relative] = data
|
|
files[relative] = {"sha256": hashlib.sha256(data).hexdigest(), "size": len(data)}
|
|
manifest = {
|
|
"schema": "livingip.gcpIapOperatorBundle.v1",
|
|
"dispatcher_version": os.environ["DISPATCHER_VERSION"],
|
|
"operation": operation,
|
|
"request_id": request_id,
|
|
"target_db": target_db,
|
|
"git_commit": head,
|
|
"ref": os.environ["GITHUB_REF"],
|
|
"workflow_ref": os.environ["GITHUB_WORKFLOW_REF"],
|
|
"files": files,
|
|
}
|
|
manifest_bytes = (json.dumps(manifest, indent=2, sort_keys=True) + "\n").encode()
|
|
bundle_dir = Path(os.environ["BUNDLE_DIR"])
|
|
bundle_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
|
|
os.chmod(bundle_dir, 0o700)
|
|
bundle_path = bundle_dir / f"{request_id}.tar.gz"
|
|
with bundle_path.open("xb") as raw:
|
|
with gzip.GzipFile(fileobj=raw, mode="wb", mtime=0) as compressed:
|
|
with tarfile.open(fileobj=compressed, mode="w", format=tarfile.PAX_FORMAT) as archive:
|
|
for relative, data in sorted({**payloads, "bundle-manifest.json": manifest_bytes}.items()):
|
|
info = tarfile.TarInfo(relative)
|
|
info.size = len(data)
|
|
info.mode = 0o600
|
|
info.mtime = 0
|
|
info.uid = info.gid = 0
|
|
info.uname = info.gname = "root"
|
|
archive.addfile(info, io.BytesIO(data))
|
|
os.chmod(bundle_path, 0o600)
|
|
PY
|
|
|
|
- name: Authenticate with short-lived workload identity federation
|
|
id: auth
|
|
uses: google-github-actions/auth@v3
|
|
with:
|
|
workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }}
|
|
service_account: ${{ steps.validate.outputs.service_account }}
|
|
create_credentials_file: true
|
|
cleanup_credentials: true
|
|
export_environment_variables: true
|
|
|
|
- name: Install Google Cloud CLI
|
|
uses: google-github-actions/setup-gcloud@v3
|
|
with:
|
|
project_id: ${{ env.PROJECT_ID }}
|
|
|
|
- name: Run fixed IAP operation
|
|
shell: bash
|
|
env:
|
|
OPERATION: ${{ inputs.operation }}
|
|
REQUEST_ID: ${{ inputs.request_id }}
|
|
TARGET_DB: ${{ inputs.target_db }}
|
|
run: |
|
|
set -euo pipefail
|
|
scripts/gcp_iap_operator.sh "${OPERATION}" "${REQUEST_ID}" "${TARGET_DB}"
|
|
|
|
- name: Upload sanitized result
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: gcp-iap-operator-${{ github.run_id }}
|
|
path: ${{ env.RESULT_DIR }}/result.json
|
|
if-no-files-found: error
|
|
retention-days: 7
|