diff --git a/perforce/LEARNINGS.md b/perforce/LEARNINGS.md index f1d5e95..57f4b00 100644 --- a/perforce/LEARNINGS.md +++ b/perforce/LEARNINGS.md @@ -12,6 +12,53 @@ them. --- +## 2026-09-14 - the typemap is one server-wide table, and a p4d container image is a second writer `[integration]` + +Learned running a Git->Perforce mirror against a p4d that ships as a Docker image and +re-applies its own engine typemap preset on every container start, not just first +provision. + +- **`p4 typemap` is a single server-wide table, so "add my depot's rows" is a + read-modify-write against state someone else also owns.** The documented pattern + (`p4 typemap -o | | p4 typemap -i`) has no compare-and-swap - any other + writer that reads, edits, and writes the whole table drops rows it doesn't know about. +- **The other writer here was the p4d image itself.** Its startup script re-applies an + engine preset on every boot, and a restart taken just to pick up an unrelated image + upgrade silently removed six depot-scoped rows a different provisioning script had + appended - nothing failed at the time, the rows were simply gone. +- **The exposure window measured ~8 minutes, not seconds**, timestamped on one real + restart. Because typemap only applies to newly-added files, a submit landing inside the + window leaves mis-typed files behind after the window closes, needing `p4 edit -t + ` to fix. +- **So verify the rows before the first `add` and fail the run - don't warn and + continue.** A sync job that warns will add a whole tree with the wrong types during a + restart window; a hard fail costs one retried run instead. +- **Without a spec depot, there's no history or author for typemap/protections edits** - + `p4 typemap -o` shows current state only, and forensics stop dead. `p4 depots` tells + you in one command whether you have one. + +## 2026-09-14 - "Wrong number of words", and what p4's exit codes do under `set -e` `[skill]` + +Three diagnostic details that cost real time chasing the entry above. + +- **"Wrong number of words for field 'X'" doesn't always mean what `p4-observe`'s + trigger-table advice says.** That advice is right for the *trigger* table (an + unquoted command containing spaces). For the **typemap** spec, the identical string + *is* whitespace: rows must be TAB-indented. Read the error against the spec you're + actually editing. +- **`p4` exits 1 with empty stdout on both "cannot connect" and "no ticket,"** verified + against a live server. That matters under `set -euo pipefail`: an assignment like + `current="$(p4 typemap -o)"` **aborts** on those failures rather than yielding an + empty string - so a script that reaches its "rows are missing" branch really did read + successfully; it's not a swallowed connection error. +- **Idempotency keyed on a description trailer must accept every width its writers + actually produce.** A mirror recording `Original-Commit: ` and matching it back + with a 40-char-only pattern missed a code path that wrote an abbreviated sha, read + that as "nothing synced," and replayed the branch from its root commit - which then + failed inside git-p4's apply step with "No valid patches in input." Matching a + variable-width sha and resolving it to the full value locally fixed it; treat an + unresolvable trailer as a hard error, not as "nothing synced." + ## 2026-07-16 - p4 trigger/webhook ingestion `[integration]` Learned wiring Perforce change-triggers into a webhook ingestion pipeline: diff --git a/unreal/LEARNINGS.md b/unreal/LEARNINGS.md index 9fa638c..2cc9a65 100644 --- a/unreal/LEARNINGS.md +++ b/unreal/LEARNINGS.md @@ -170,3 +170,10 @@ No secrets - reference credential *locations*, never paste them. is a node action; bare `nvidia/cuda` images die on step one). catthehacker act-22.04 + the NVIDIA container toolkit + `container.options: "--gpus all"` works; driver injection gives nvidia-smi-level access, CUDA only if the image adds it. +15. **Two traps when authoring the automation scripts themselves, both of which hang + instead of erroring.** A PowerShell `[Parameter(Mandatory=$true)]` argument + silently prompts on stdin when omitted, so a non-interactive SSH invocation just + blocks forever - validate the argument by hand rather than trusting the parameter + binder to catch a missing value. And `ssh -n` redirects stdin from `/dev/null`, + which silently swallows a heredoc meant to feed a remote `bash -s` - the remote + script runs with no input and nothing reports an error.