test(e2e): bind finance release to exact validation
This commit is contained in:
@@ -30,6 +30,7 @@ services:
|
||||
ALLOWED_ORIGINS: http://frontend
|
||||
SOURCE_REPOSITORY_IDENTITY_FILE: /run/source-identity/identity.json
|
||||
GITEA_API_BASE_URL: http://gitea:3000/api/v1
|
||||
E2E_BACKEND_URL: http://127.0.0.1:8000
|
||||
FULL_FLOW_ENV_FILE_UID: ${E2E_PRIVATE_ENV_UID:?Set E2E_PRIVATE_ENV_UID}
|
||||
FULL_FLOW_ENV_FILE_GID: ${E2E_PRIVATE_ENV_GID:?Set E2E_PRIVATE_ENV_GID}
|
||||
volumes:
|
||||
|
||||
@@ -123,30 +123,52 @@ def export(driver, repo, metadata):
|
||||
driver.call("git-author-profile", "PATCH", "/api/profile/preferences", {
|
||||
"git_username": "full-flow-admin", "git_email": "full-flow@example.test",
|
||||
"git_personal_access_token": driver.git_token})
|
||||
driver.call("export-finance-dev", "POST", repo+"/sync"+suffix+"&source_env_id=full-flow-dev")
|
||||
synced = driver.call("export-finance-dev", "POST", repo+"/sync"+suffix+"&source_env_id=full-flow-dev")
|
||||
driver.require("finance-dev-sync-success", synced.get("status") == "success")
|
||||
driver.call("commit-finance-dev", "POST", repo+"/commit"+suffix,
|
||||
{"message": "Synthetic finance million-row fixture", "files": []})
|
||||
driver.call("push-finance-dev", "POST", repo+"/push"+suffix)
|
||||
driver.call("reject-direct-finance-prod", "POST", repo+"/deploy"+suffix,
|
||||
direct_prod = driver.call("reject-direct-finance-prod", "POST", repo+"/deploy"+suffix,
|
||||
{"stage": "prod"}, expected=(409,))
|
||||
driver.require("finance-direct-prod-refusal-exact",
|
||||
direct_prod.get("detail") == "Create and publish a named dashboard release before deploying to PROD")
|
||||
driver.call("deploy-finance-preprod", "POST", repo+"/deploy"+suffix, {"stage": "preprod"})
|
||||
driver.call("reject-unvalidated-finance-release", "POST", repo+"/releases"+suffix,
|
||||
metadata, expected=(409,))
|
||||
deployment_status = driver.call("finance-preprod-deployment-status", "GET",
|
||||
repo+"/deployment-status"+suffix)
|
||||
preprod_rows = [row for row in deployment_status.get("environments", []) if row.get("stage") == "preprod"]
|
||||
driver.require("finance-preprod-deployment-identity-present", len(preprod_rows) == 1
|
||||
and isinstance(preprod_rows[0].get("commit_hash"), str)
|
||||
and bool(preprod_rows[0]["commit_hash"])
|
||||
and isinstance(preprod_rows[0].get("content_hash"), str)
|
||||
and bool(preprod_rows[0]["content_hash"]))
|
||||
preprod_identity = {key: preprod_rows[0][key] for key in ("commit_hash", "content_hash")}
|
||||
unvalidated = driver.call("reject-unvalidated-finance-release", "POST", repo+"/releases"+suffix,
|
||||
metadata, expected=(409,))
|
||||
driver.require("finance-unvalidated-release-refusal-exact",
|
||||
unvalidated.get("detail") == "Validate the current PREPROD deployment before creating a release")
|
||||
validation = driver.call("validate-finance-preprod", "POST", repo+"/deployment-validation"+suffix,
|
||||
{"stage": "preprod", "comment": "Authorized synthetic finance review"})
|
||||
stage = next((s for s in validation["environments"] if s["stage"] == "preprod"), {})
|
||||
driver.require("finance-preprod-validated-exact", stage.get("validation_status") == "validated"
|
||||
and stage.get("drift_status") == "in_sync", deployment=stage)
|
||||
driver.require("finance-preprod-validation-preserves-identity",
|
||||
all(stage.get(key) == value for key, value in preprod_identity.items()))
|
||||
return preprod_identity
|
||||
# #endregion FullFlow.FinanceRelease.Export
|
||||
|
||||
|
||||
# #region FullFlow.FinanceRelease.Publish [C:4] [TYPE Function]
|
||||
# @BRIEF Require approval and publish the same immutable PREPROD-tested release to PROD.
|
||||
def publish(driver, repo, metadata):
|
||||
def publish(driver, repo, metadata, preprod_identity):
|
||||
suffix = "?env_id=full-flow-dev"
|
||||
release = driver.call("create-finance-release", "POST", repo+"/releases"+suffix,
|
||||
metadata, expected=(201,))
|
||||
driver.ids["release_id"] = release["id"]
|
||||
identity_valid = all(isinstance(preprod_identity.get(key), str) and preprod_identity[key]
|
||||
and release.get(key) == preprod_identity[key]
|
||||
for key in ("commit_hash", "content_hash"))
|
||||
driver.require("finance-release-preserves-preprod-identity", identity_valid,
|
||||
commit_hash=release.get("commit_hash"), content_hash=release.get("content_hash"))
|
||||
driver.require("finance-release-awaits-human", release["status"] == "awaiting_approval")
|
||||
approved = driver.call("approve-finance-release", "POST",
|
||||
repo+f"/releases/{release['id']}/approve"+suffix,
|
||||
@@ -158,7 +180,11 @@ def publish(driver, repo, metadata):
|
||||
ledger = driver.call("finance-release-ledger", "GET", repo+"/releases"+suffix)
|
||||
current = next(r for r in ledger if r["id"] == release["id"])
|
||||
driver.require("finance-published-exact-commit", current["status"] == "published"
|
||||
and current["commit_hash"] == release["commit_hash"])
|
||||
and current["id"] == release["id"]
|
||||
and current["commit_hash"] == release["commit_hash"]
|
||||
and current["content_hash"] == release["content_hash"]
|
||||
and current["commit_hash"] == preprod_identity["commit_hash"]
|
||||
and current["content_hash"] == preprod_identity["content_hash"])
|
||||
driver.output.joinpath("published-release.json").write_text(json.dumps(current, indent=2)+"\n")
|
||||
# #endregion FullFlow.FinanceRelease.Publish
|
||||
|
||||
@@ -174,7 +200,10 @@ def main():
|
||||
args = parser.parse_args()
|
||||
private_environment(args.env_file)
|
||||
asset = assets(args.assets)
|
||||
asset["backend_url"] = os.environ.get("E2E_BACKEND_URL", "http://127.0.0.1:8000")
|
||||
backend_url = os.environ.get("E2E_BACKEND_URL")
|
||||
if backend_url != "http://127.0.0.1:8000":
|
||||
raise ValueError("E2E_BACKEND_URL_REQUIRED")
|
||||
asset["backend_url"] = backend_url
|
||||
driver = Driver(asset, args.output)
|
||||
driver.secrets.append(os.environ["CLICKHOUSE_PASSWORD"])
|
||||
driver.phase = "finance-release"
|
||||
@@ -186,8 +215,8 @@ def main():
|
||||
driver.login()
|
||||
driver.setup()
|
||||
repository(driver, repo)
|
||||
export(driver, repo, metadata)
|
||||
publish(driver, repo, metadata)
|
||||
preprod_identity = export(driver, repo, metadata)
|
||||
publish(driver, repo, metadata, preprod_identity)
|
||||
except (Blocked, KeyError, StopIteration, ValueError, httpx.HTTPError) as exc:
|
||||
driver.record("finance-release-stopped", "BLOCKED", reason=str(exc))
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user