mirror of
https://github.com/Sea-Haven-Industries/payments-dashboard.git
synced 2026-10-07 03:32:08 +00:00
* ci: pin ci-terraform to v1.0.26 That release classifies a pull request against the merge parent, so a re-run after main moves is not treated as a mixed app and Terraform change. * fix(iam): trust the Lambda reusable at any pin A digest in the deploy role meant every reusable bump had to edit Terraform before dev and prod could assume the role.
129 lines
5.5 KiB
JavaScript
129 lines
5.5 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 removed = readFileSync(join(TERRAFORM, "removed.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("does not declare in-repo hcptf roles", () => {
|
|
assert.equal(existsSync(join(TERRAFORM, "hcp_iam.tf")), false);
|
|
assert.equal(existsSync(join(TERRAFORM, "lambda_boundary.tf")), false);
|
|
assert.match(lambdaTf, /permissions_boundary\s+=\s+local\.lambda_boundary_arn/);
|
|
assert.match(
|
|
locals,
|
|
/arn:aws:iam::\$\{local\.account_id\}:policy\/tf-managed\/payments-dashboard-lambda-boundary/,
|
|
);
|
|
assert.match(removed, /from = aws_iam_role\.hcptf_apply/);
|
|
assert.match(removed, /from = aws_iam_policy\.lambda_boundary/);
|
|
assert.match(removed, /destroy\s+=\s+false/);
|
|
assert.doesNotMatch(locals, /apply_role/);
|
|
});
|
|
|
|
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 the Terraform callable behind ci-complete", () => {
|
|
assert.doesNotMatch(ci, /ci-typescript-cdk/);
|
|
assert.doesNotMatch(ci, /run-sam-validate/);
|
|
assert.match(ci, /npm test/);
|
|
assert.match(ci, /ci-terraform\.yaml@[0-9a-f]{40} # v/);
|
|
assert.match(ci, /ci-autofix\.yaml@[0-9a-f]{40} # v/);
|
|
assert.doesNotMatch(ci, /ci-terraform\.yaml@\*/);
|
|
assert.doesNotMatch(ci, /ci-autofix\.yaml@\*/);
|
|
assert.match(ci, /presets: prettier,terraform/);
|
|
assert.match(ci, /npm run format:check/);
|
|
assert.match(ci, /src\//);
|
|
assert.match(ci, /package\.json/);
|
|
assert.match(ci, /package-lock\.json/);
|
|
assert.match(ci, /hotfix\/\*\*/);
|
|
assert.match(ci, /release\/\*\*/);
|
|
assert.match(ci, /name: ci-complete/);
|
|
assert.doesNotMatch(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(githubDeploy, /StringLike[\s\S]{0,80}job_workflow_ref/);
|
|
assert.doesNotMatch(githubDeploy, /StringEquals[\s\S]{0,80}job_workflow_ref/);
|
|
assert.match(locals, /cd-hcp-lambda\.yaml@\*/);
|
|
assert.match(deploy, /cd-hcp-lambda\.yaml@[0-9a-f]{40} # v/);
|
|
assert.doesNotMatch(deploy, /cd-hcp-lambda\.yaml@\*/);
|
|
assert.doesNotMatch(githubDeploy, /deploy\.yaml@refs\/heads/);
|
|
assert.doesNotMatch(variables, /github_deploy_branch/);
|
|
});
|
|
});
|