mirror of
https://github.com/Sea-Haven-Industries/engineering-handbook.git
synced 2026-09-30 03:23:14 +00:00
Merge pull request #26 from Sea-Haven-Industries/docs/audit-2026-07-28-fixes
Some checks failed
ci / ci / ci (push) Has been cancelled
Some checks failed
ci / ci / ci (push) Has been cancelled
docs: align deploy policy, workflow pins, and node runtime with current standards
This commit is contained in:
commit
1fc8370890
4 changed files with 56 additions and 15 deletions
|
|
@ -13,13 +13,21 @@ These apply to every Lambda in every project. Verify, don't assume.
|
|||
|
||||
| Setting | Value |
|
||||
|---|---|
|
||||
| Runtime | Python 3.12 or Node 24.x |
|
||||
| Runtime | Python 3.12 or Node 24.x (`nodejs24.x`) |
|
||||
| Architecture | arm64 |
|
||||
| Log retention | 60 days (explicit in IaC template) |
|
||||
| Naming | kebab-case, matching the stack name prefix |
|
||||
|
||||
Never rely on the CloudWatch default for log retention. Always set `RetentionInDays` explicitly in the template.
|
||||
|
||||
### Node runtime
|
||||
|
||||
This is the canonical statement; [dev-environment.md](dev-environment.md#nodejs) and [cdk-project-layout.md](cdk-project-layout.md#lambda-defaults) defer to it.
|
||||
|
||||
- **`nodejs24.x` is the standard.** Every new Node Lambda targets it, set explicitly in the IaC template.
|
||||
- **`nodejs22.x` is legacy only.** It is valid for functions that already run on it, and those move to 24.x before the AWS deprecation date of 2027-04-30. Do not start a new function on it.
|
||||
- **Never target `nodejs26.x`,** including once AWS ships it. Lambda applies runtime updates automatically, so a fresh major is only adopted after it has been generally available on Lambda for a full quarter, and only by a deliberate change to this page. Odd majors (25.x, 27.x) never become Lambda runtimes at all.
|
||||
|
||||
## CDK Version Policy
|
||||
|
||||
Pin `aws-cdk-lib` to an exact version (no `^`, `~`, or `>=`) and let Dependabot keep it current. There is no static "blessed version" — the org standard is the latest release that passes the gates below. Do not add blanket `dependabot.yml` ignore entries for `aws-cdk-lib`; that is how pins rot into carrying known vulnerabilities.
|
||||
|
|
|
|||
|
|
@ -49,10 +49,12 @@ import { ProjectNameStack } from '../lib/project-name-stack';
|
|||
const app = new cdk.App();
|
||||
new ProjectNameStack(app, 'ProjectNameStack', {
|
||||
stackName: 'project-name',
|
||||
env: { account: '328440206208', region: 'us-east-1' },
|
||||
env: { region: 'us-east-1' },
|
||||
});
|
||||
```
|
||||
|
||||
Set `region` only. The account comes from the credentials the deploy runs with (the repo's OIDC deploy role), so leaving it unset keeps one entry point working across accounts and keeps the synthesized template account-agnostic. Hard-coding an account ID also literalizes `AWS::AccountId` in the template, which turns unrelated resources into replacement candidates on the next diff.
|
||||
|
||||
### `lib/project-name-stack.ts`
|
||||
|
||||
All resource definitions. For larger projects, split into multiple constructs under `lib/` and compose them in the stack file. Keep the stack class thin -- it wires constructs together, not defines low-level resources.
|
||||
|
|
@ -141,7 +143,7 @@ Same defaults as SAM projects. Verify these on every Lambda in every CDK stack:
|
|||
|
||||
| Setting | Value |
|
||||
|---|---|
|
||||
| Runtime | Python 3.12 or Node 24.x |
|
||||
| Runtime | Python 3.12 or Node 24.x (`nodejs24.x`) |
|
||||
| Architecture | arm64 |
|
||||
| Log retention | 60 days (explicit `RetentionInDays`) |
|
||||
| Naming | kebab-case, prefixed with stack name |
|
||||
|
|
@ -155,7 +157,7 @@ new logs.LogGroup(this, 'HandlerLogs', {
|
|||
});
|
||||
```
|
||||
|
||||
See [aws-infrastructure.md](aws-infrastructure.md#lambda-defaults).
|
||||
See [aws-infrastructure.md](aws-infrastructure.md#lambda-defaults), and [Node runtime](aws-infrastructure.md#node-runtime) for the canonical rule on `nodejs24.x` versus the `nodejs22.x` legacy case.
|
||||
|
||||
## CI/CD
|
||||
|
||||
|
|
@ -171,7 +173,7 @@ on:
|
|||
branches: [main]
|
||||
jobs:
|
||||
ci:
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/ci-typescript-cdk.yaml@main
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/ci-typescript-cdk.yaml@<full-commit-sha> # main
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
|
|
@ -182,14 +184,14 @@ on:
|
|||
branches: [main]
|
||||
jobs:
|
||||
deploy:
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/cd-cdk.yaml@main
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/cd-cdk.yaml@<full-commit-sha> # main
|
||||
with:
|
||||
node-version: "24"
|
||||
secrets:
|
||||
deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
||||
```
|
||||
|
||||
Always pass `node-version: "24"` explicitly. See [cicd.md](cicd.md) for the full pipeline convention.
|
||||
Always pass `node-version: "24"` explicitly. Reusable workflow refs are pinned to a full 40-character commit SHA of the central `.github` repo with a trailing `# main` comment, never to a branch or tag; see [Workflow Ref Pinning](cicd.md#workflow-ref-pinning). Pin to the current tip of that repo's `main` when adding a caller by hand and let Dependabot advance it. See [cicd.md](cicd.md) for the full pipeline convention.
|
||||
|
||||
## Bedrock Agents
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ When troubleshooting Python issues, check that pyenv is active before anything e
|
|||
## Node.js
|
||||
|
||||
- Local: Node 24 / npm 11 (generates `lockfileVersion: 3`)
|
||||
- Lambda: Node 22.x or 24.x (set explicitly in IaC)
|
||||
- Lambda: `nodejs24.x`, set explicitly in IaC. `nodejs22.x` is legacy only and never `nodejs26.x`; see [AWS Infrastructure](aws-infrastructure.md#node-runtime) for the canonical rule
|
||||
- Reusable workflows: always pass `node-version: "24"` (the default is 22 / npm 10, which can fail `npm ci` on npm 11 lockfiles)
|
||||
|
||||
## macOS launchd and the TCC Sandbox
|
||||
|
|
|
|||
|
|
@ -52,19 +52,30 @@ The integration also accepts inline commands in commit messages to act on the is
|
|||
|
||||
Transition names are case-insensitive and match the issue's workflow (`#in-progress`, `#done`). Use these sparingly; the link itself is the main goal, not driving the whole workflow from commits.
|
||||
|
||||
## Deploy-Then-Merge
|
||||
## Deploying
|
||||
|
||||
CI-on-merge is the only sanctioned deploy path. A change reaches an environment by merging its PR into `main` and letting the repo's pipeline deploy, or through a `workflow_dispatch` run of that same pipeline where the repo configures one. Nobody deploys from a workstation.
|
||||
|
||||
The standard flow for changes that deploy to AWS:
|
||||
|
||||
1. Create a feature branch (`feature/add-receipt-parser`)
|
||||
2. Develop and commit locally
|
||||
3. Open a PR via `gh pr create`
|
||||
4. Merge the feature branch into `main` locally
|
||||
5. Deploy to the target environment (`sam deploy`, etc.)
|
||||
6. Verify in production
|
||||
7. Merge the PR on GitHub
|
||||
4. Get the review, and confirm CI is green (`gh pr checks`)
|
||||
5. Merge the PR on GitHub
|
||||
6. The pipeline deploys on the merge to `main`, or on a `workflow_dispatch` run where the repo is set up that way
|
||||
7. Verify the deployed environment; if it is wrong, roll forward with a follow-up PR
|
||||
|
||||
This ensures production works before the PR closes. If the deploy fails, the PR stays open and `main` on GitHub is still clean.
|
||||
A local deploy puts code into an environment that no reviewed commit describes, and its result depends on whoever ran it having the right credentials and a clean working tree. The pipeline deploys a known commit with the repo's own OIDC role every time. See [cicd.md](cicd.md).
|
||||
|
||||
### Legacy exception: deploy-then-merge
|
||||
|
||||
Merging the feature branch into `main` locally, deploying by hand (`sam deploy`, `cdk deploy`), and only then merging the PR on GitHub is a legacy pattern. It is not a default and it is not available on request. Both of these must hold:
|
||||
|
||||
- **The change is data-loss-prone and stateful.** A resource replacement that would recreate a table or bucket, a one-way schema or data migration, or a stack operation that has to be watched and aborted mid-flight, where an automated deploy or rollback could destroy data.
|
||||
- **Adam has signed off on that specific deploy in advance.**
|
||||
|
||||
Write the justification into the PR description under `## Notes`: what the stateful risk is, and where the sign-off happened. An exception that is not written down is not an exception, so use the pipeline.
|
||||
|
||||
## Push Discipline
|
||||
|
||||
|
|
@ -116,10 +127,30 @@ Recommended hooks live in [`hooks/`](hooks/) — copy them into `.git/hooks/` wh
|
|||
Install for a Node.js project:
|
||||
|
||||
```bash
|
||||
cp ~/Documents/repositories/engineering-handbook/hooks/pre-push .git/hooks/pre-push
|
||||
cp ~/Documents/repositories/seahaven/engineering-handbook/hooks/pre-push .git/hooks/pre-push
|
||||
chmod +x .git/hooks/pre-push
|
||||
```
|
||||
|
||||
### `core.hooksPath` shadows, it does not merge
|
||||
|
||||
`core.hooksPath` names a single directory, not a search path. Setting it in a repo (for example to a tracked `.githooks/`) makes git run hooks *only* from there and ignore the machine-global hooks directory completely. Where that global directory holds a mandatory hook, such as the workstation security `pre-push`, a repo-local `core.hooksPath` silently disables it: no error, no output, no gate.
|
||||
|
||||
A repo that sets its own `core.hooksPath` must ship a `pre-push` that re-execs the global hook instead of replacing it:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
GLOBAL="${SH_GLOBAL_HOOKS:-$HOME/.config/git/hooks}/pre-push"
|
||||
[ -x "$GLOBAL" ] && exec "$GLOBAL" "$@" # passes args and stdin, preserves the exit code
|
||||
exit 0 # nothing to delegate to
|
||||
```
|
||||
|
||||
Two consequences:
|
||||
|
||||
- An installer that sets `core.hooksPath` must verify the shim delegates **before** it touches the config, and refuse to install if the delegation is missing or broken.
|
||||
- A tracked hooks directory only exists on branches that contain it, so the gate is off on every branch that predates it. Land the hooks directory on all long-lived branches before installing.
|
||||
|
||||
Check what is actually in effect with `git config core.hooksPath` and `git config --local core.hooksPath`, then confirm the repo's `pre-push` still execs the global one.
|
||||
|
||||
## Cleaning Up
|
||||
|
||||
After a PR is merged:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue