import assert from "node:assert/strict"; import { existsSync, readFileSync } from "node:fs"; import { dirname, join } from "node:path"; import { describe, it } from "node:test"; import { fileURLToPath } from "node:url"; const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", ".."); const TERRAFORM = join(ROOT, "terraform"); const lambdaTf = readFileSync(join(TERRAFORM, "lambda.tf"), "utf8"); const hcpIam = readFileSync(join(TERRAFORM, "hcp_iam.tf"), "utf8"); const deploy = readFileSync(join(ROOT, ".github", "workflows", "deploy.yaml"), "utf8"); const ci = readFileSync(join(ROOT, ".github", "workflows", "ci.yaml"), "utf8"); const locals = readFileSync(join(TERRAFORM, "locals.tf"), "utf8"); const variables = readFileSync(join(TERRAFORM, "variables.tf"), "utf8"); const versions = readFileSync(join(TERRAFORM, "versions.tf"), "utf8"); const githubDeploy = readFileSync(join(TERRAFORM, "iam_github_deploy.tf"), "utf8"); describe("HCP Terraform seam (PLAT-79)", () => { it("removes the SAM template", () => { assert.equal(existsSync(join(ROOT, "template.yaml")), false); assert.equal(existsSync(join(ROOT, "samconfig.toml.example")), false); }); it("ignores Lambda code attributes so zip CD is not drift", () => { for (const attr of ["filename", "s3_bucket", "s3_key", "s3_object_version", "source_code_hash"]) { assert.match(lambdaTf, new RegExp(attr)); } assert.match(lambdaTf, /lifecycle/); assert.match(lambdaTf, /ignore_changes/); }); it("keeps schedules disabled by default", () => { const chunk = variables.split('variable "schedules_enabled"')[1].split("variable ")[0]; assert.match(chunk, /default\s+= false/); }); it("selects dev and prod workspaces by tag", () => { assert.match(versions, /app:payments-dashboard/); assert.doesNotMatch(versions, /name = "payments-dashboard-prod"/); assert.match(locals, /seahaven-\$\{var\.environment\}/); assert.match(locals, /710827005802/); assert.match(locals, /011934824531/); assert.match(variables, /contains\(\["dev", "prod"\], var\.environment\)/); }); it("declares in-repo hcptf roles", () => { assert.match(locals, /apply_role\s+= "hcptf-payments-dashboard"/); assert.match(locals, /plan_role\s+= "hcptf-payments-dashboard-plan"/); assert.match(hcpIam, /hcptf_apply/); assert.match(hcpIam, /DenyCreatePolicy/); }); it("calls the Lambda zip reusable for dev and prod", () => { assert.match(deploy, /release:\s*\n\s*types: \[published\]/); assert.doesNotMatch(deploy, /cd-sam/); assert.doesNotMatch(deploy, /aws lambda update-function-code/); assert.match(deploy, /gh release create vX\.Y\.Z --target main/); assert.doesNotMatch(deploy, /release\.yaml@/); assert.match(deploy, /cd-hcp-lambda\.yaml@/); assert.match(deploy, /environment: dev/); assert.match(deploy, /environment: prod/); assert.match(deploy, /ship-gate: true/); assert.match(deploy, /ssm-prefix: \/payments-dashboard\/deploy/); assert.match(deploy, /function-keys: process_csv,slack_app_home,fetch_boa,expense_receiver,expense_processor/); }); it("runs npm test and terraform validate behind ci / ci", () => { assert.doesNotMatch(ci, /ci-typescript-cdk/); assert.doesNotMatch(ci, /run-sam-validate/); assert.match(ci, /npm test/); assert.match(ci, /terraform fmt -check/); assert.match(ci, /terraform init -backend=false/); assert.match(ci, /terraform validate/); assert.match(ci, /name: ci \/ ci/); }); it("names the five live functions", () => { for (const name of [ "payments-processPaymentCsv", "payments-slackAppHome", "payments-fetchBoaTransactions", "payments-expenseReceiver", "payments-expenseProcessor", ]) { assert.match(locals, new RegExp(name)); } assert.doesNotMatch(locals, /payments-processPayrollEmail/); }); it("pins GitHub deploy trust to the Lambda reusable", () => { const prodSubs = locals.split("github_oidc_subs_prod")[1].split("github_oidc_subs_dev")[0]; assert.match(prodSubs, /environment:prod/); assert.doesNotMatch(prodSubs, /environment:dev/); assert.match(githubDeploy, /github_oidc_subs/); assert.match(githubDeploy, /job_workflow_ref/); assert.match(locals, /cd-hcp-lambda\.yaml@ee5b843ca105422b679c3fdeb9eaa68c6e500a85/); assert.match(deploy, /cd-hcp-lambda\.yaml@ee5b843ca105422b679c3fdeb9eaa68c6e500a85/); assert.doesNotMatch(githubDeploy, /cd-hcp-lambda\.yaml@\*/); assert.doesNotMatch(locals, /cd-hcp-lambda\.yaml@\*/); assert.doesNotMatch(githubDeploy, /deploy\.yaml@refs\/heads/); assert.doesNotMatch(variables, /github_deploy_branch/); }); it("includes provider-6 S3 Get* needed for refresh", () => { assert.match(hcpIam, /s3:GetLifecycleConfiguration/); assert.match(hcpIam, /s3:GetReplicationConfiguration/); assert.match(hcpIam, /s3:GetBucketReplication/); }); });