03edd82d53
The W6 'unset NOVA_GITEA_TOKEN' line in scripts/run_platform.sh tripped the test_no_forge_mentions guard (REQ-230 forbids forge-specific names in synced files). Renamed to NOVA_FORGE_TOKEN (forge-agnostic); .env.secrets adds NOVA_FORGE_TOKEN as an alias; config.json scopes now map forge + gitea -> NOVA_FORGE_TOKEN. scripts/rotate_spike_key.sh (excluded from the sync scan) keeps the NOVA_GITEA_TOKEN backward-compat fallback for local runs. Full suite green (844 passed). ---ci--- project: acdl phase: 3 milestone: v1.26 status: execute wave: W6 ---
118 lines
4.8 KiB
Python
118 lines
4.8 KiB
Python
"""REQ-106: deploy workflow environment input + run_platform.sh --environment.
|
|
The deploy workflow declares the environment input and the resolver
|
|
supports environment_override.
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from core.contract_resolver import resolve
|
|
|
|
GITHUB = ROOT / ".github" / "workflows" / "deploy.yml"
|
|
|
|
|
|
def test_deploy_workflow_exists():
|
|
assert GITHUB.is_file()
|
|
|
|
|
|
def test_deploy_workflow_has_environment_input():
|
|
text = GITHUB.read_text()
|
|
assert "environment:" in text
|
|
assert "Target environment override" in text
|
|
# The input is declared in the workflow_call inputs section.
|
|
assert 'default: ""' in text
|
|
|
|
|
|
def test_deploy_workflow_passes_env_flag_to_run_platform():
|
|
text = GITHUB.read_text()
|
|
assert "--environment" in text
|
|
assert "ENV_FLAG" in text
|
|
assert "inputs.environment" in text
|
|
|
|
|
|
def test_resolver_environment_override_changes_env():
|
|
"""environment_override changes the resolved environment."""
|
|
stack = resolve(str(ROOT / "contracts" / "static-assets.yml"),
|
|
environment_override="qa")
|
|
s3 = [r for r in stack["resources"] if r["type"] == "aws:s3:bucket"][0]
|
|
assert "qa" in s3["inputs"]["bucket_name"]
|
|
|
|
|
|
def test_resolver_environment_override_prod():
|
|
stack = resolve(str(ROOT / "contracts" / "static-assets.yml"),
|
|
environment_override="prod")
|
|
s3 = [r for r in stack["resources"] if r["type"] == "aws:s3:bucket"][0]
|
|
assert "prod" in s3["inputs"]["bucket_name"]
|
|
|
|
|
|
def test_resolver_environment_override_dr():
|
|
stack = resolve(str(ROOT / "contracts" / "static-assets.yml"),
|
|
environment_override="dr")
|
|
s3 = [r for r in stack["resources"] if r["type"] == "aws:s3:bucket"][0]
|
|
assert "dr" in s3["inputs"]["bucket_name"]
|
|
|
|
|
|
def test_resolver_no_override_uses_contract_env():
|
|
stack = resolve(str(ROOT / "contracts" / "static-assets.yml"))
|
|
s3 = [r for r in stack["resources"] if r["type"] == "aws:s3:bucket"][0]
|
|
assert "dev" in s3["inputs"]["bucket_name"]
|
|
|
|
|
|
def test_resolver_override_none_uses_contract_env():
|
|
"""Passing environment_override=None uses the contract's environment."""
|
|
stack = resolve(str(ROOT / "contracts" / "static-assets.yml"),
|
|
environment_override=None)
|
|
s3 = [r for r in stack["resources"] if r["type"] == "aws:s3:bucket"][0]
|
|
assert "dev" in s3["inputs"]["bucket_name"]
|
|
|
|
|
|
def test_run_platform_sh_has_environment_flag():
|
|
text = (ROOT / "scripts" / "run_platform.sh").read_text()
|
|
assert "--environment" in text
|
|
assert "ENVIRONMENT_OVERRIDE" in text
|
|
assert "NOVA_ENVIRONMENT_OVERRIDE" in text
|
|
assert "ACDL_ENVIRONMENT_OVERRIDE" not in text
|
|
|
|
|
|
def test_deploy_workflow_aws_region_from_secret_with_fallback():
|
|
"""SPEC §5.2: aws-region is read from the AWS_DEFAULT_REGION secret (not
|
|
hardcoded). The ``|| 'us-east-1'`` fallback preserves backwards-compat
|
|
for consumers that haven't set the secret."""
|
|
text = GITHUB.read_text()
|
|
assert "aws-region: ${{ secrets.AWS_DEFAULT_REGION || 'us-east-1' }}" in text
|
|
# The hardcoded us-east-1 for the configure-aws-credentials step is gone.
|
|
assert "aws-region: us-east-1" not in text
|
|
|
|
|
|
def test_deploy_workflow_platform_checkout_ref_matches_milestone():
|
|
"""SPEC §7.2: the platform checkout ref matches the consumer's @v1.25
|
|
pin (the current v1.26 milestone's floating tag)."""
|
|
import yaml
|
|
wf = yaml.safe_load(GITHUB.read_text())
|
|
if True in wf:
|
|
wf["on"] = wf[True]
|
|
deploy_job = wf["jobs"]["deploy"]
|
|
checkout_steps = [s for s in deploy_job["steps"]
|
|
if "checkout" in s.get("uses", "")]
|
|
platform_checkout = next(
|
|
(s for s in checkout_steps if s.get("with", {}).get("path") == "platform"),
|
|
None)
|
|
assert platform_checkout is not None, "must have a platform repo checkout"
|
|
assert platform_checkout["with"]["ref"] == "v1.25", \
|
|
"platform checkout ref must be v1.25 (matching the consumer's @v1.25 pin)"
|
|
|
|
|
|
def test_run_platform_sh_local_fallback_unsets_raw_nova_aws_vars():
|
|
"""SPEC §5.2: the local .env.secrets fallback must NOT leave raw
|
|
NOVA_AWS_* / the forge-token name in the shell env — only the
|
|
canonical AWS_* names. This is the v1.8 blocked_env_vars guard."""
|
|
text = (ROOT / "scripts" / "run_platform.sh").read_text()
|
|
# The fallback exports the canonical AWS_* names...
|
|
assert 'export AWS_ACCESS_KEY_ID="$NOVA_AWS_ACCESS_KEY_ID"' in text
|
|
assert 'export AWS_SECRET_ACCESS_KEY="$NOVA_AWS_SECRET_ACCESS_KEY"' in text
|
|
assert 'export AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-us-east-1}"' in text
|
|
# ...then unsets the raw NOVA_AWS_* + the forge-agnostic forge-token name.
|
|
assert "unset NOVA_AWS_ACCESS_KEY_ID NOVA_AWS_SECRET_ACCESS_KEY NOVA_FORGE_TOKEN" in text
|