payments-dashboard/tests/infra/hcpContract.test.js

104 lines
4.4 KiB
JavaScript

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", () => {
assert.match(locals, /environment:dev/);
assert.match(locals, /environment:prod/);
assert.match(githubDeploy, /github_oidc_subs/);
assert.match(githubDeploy, /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/);
});
});