Add Perforce keyword-based version stamping to the p4lf binary, and wrap up the macOS development phase in preparation for Linux integration testing.
Added in CL 32818 (previous session). Key targets:
| Target | Purpose |
|---|---|
make build |
Current platform → bin/p4lf |
make build-linux |
Linux amd64 → bin/p4lf-linux-amd64 (primary deploy target) |
make build-linux-arm64 |
Linux arm64 |
make build-darwin / build-darwin-amd64 |
macOS builds |
make build-all |
All four platforms |
make check |
vet + fmt + test (CI gate) |
make install INSTANCE=1 |
Deploy binary + systemd unit to SDP paths |
make release VERSION=x.y.z |
All platforms + dist/ tarballs |
internal/version/version.go is stored in Perforce as type text+k.
Perforce expands three keywords on every submit/sync of this file:
| Constant | Example after expansion |
|---|---|
P4ID |
$Id: //p4lf/dev/internal/version/version.go#2 $ |
P4Change |
$Change: 32820 $ |
P4DateTime |
$DateTime: 2026/06/25 12:14:37 $ |
SemVer is a hand-maintained var ("0.1.0") that can also be overridden
at build time: make build VERSION=1.0.0.
p4lf -version output:
p4lf 0.1.0 (CL 32820, //p4lf/dev#2, 2026/06/25)
Verifiable without running the binary:
strings p4lf | grep 'Id:\|Change:\|DateTime:'
The regex patterns that parse the keyword values (e.g., \$Id:\s*...) must
NOT themselves be expanded by Perforce. The fix: define const dollar = "\x24"
(dollar sign in hex) and build patterns via string concatenation:
var idRe = regexp.MustCompile(`\` + dollar + `Id:\s*(//[^\s#]+)(#\d+)\s*\` + dollar)
P4 never sees $Id: as a contiguous byte sequence in the source, so it leaves
the regex patterns alone. This was a bug in the first submit (CL 32819) and
fixed in CL 32820.
The grep SemVer\s*= also matched the -ldflags example in the package doc
comment, corrupting the VERSION value. Fixed by anchoring: ^var SemVer.
| CL | Description |
|---|---|
| 32818 | Initial Go implementation (all source files, Makefile, config, tailer, chunker, logger, systemd, example config, session logs) |
| 32819 | Version stamping (version.go as text+k) — had regex expansion bug |
| 32820 | Fix regex patterns with const dollar = "\x24" |
| 32821 | Fix Makefile VERSION grep anchor |
Latest: //p4lf/dev at CL 32821, all make check tests passing, all four
platform binaries building cleanly.
The following should be verified on a Linux host with an SDP environment and running p4d instance:
go version # Confirm Go is available (1.20+ required)
p4 sync # Sync workspace
make build # Should produce bin/p4lf
bin/p4lf -version # Should show: p4lf 0.1.0 (CL 32821, //p4lf/dev#N, ...)
cp p4lf.cfg.example /tmp/test-p4lf.cfg
# Edit: set P4LogFile to your P4LOG path
bin/p4lf -config /tmp/test-p4lf.cfg # Should start and log to /tmp/p4lf.log (since $LOGS not set)
LogTailDelay interval, verify log.*.gz files appear in LogChunksDirgunzip -c log.*.gz | head should show real P4LOG content$LOGS/p4lf.state contains inode + offset JSON# Simulate a rotation while p4lf is running:
mv $P4LOG $P4LOG.old && touch $P4LOG
# p4lf should detect the inode change, log a rotation event, and reset to offset 0
kill -HUP $(pidof p4lf)
# Should reload config and rotate p4lf.log
sudo make install INSTANCE=1
# Edit /p4/common/site/log_feeder/p4lf.cfg
sudo systemctl enable p4lf
sudo systemctl start p4lf
sudo systemctl status p4lf
journalctl -u p4lf -f
sudo systemctl stop p4lf
# Should do final flush, write state, clean exit
# Verify state file is current
/p4/common/bin/p4_vars
for the $LOGS and $P4LOG env vars; verify this path is correct for the
target SDP installation.WaitUntilGuardsPassed timeout: currently waits indefinitely; may want a
max-wait-and-warn after some number of retries.# P4LF Session Log — 2026-06-25 (Session 3: Version Stamping + Handoff to Linux Testing) ## Session Goal Add Perforce keyword-based version stamping to the p4lf binary, and wrap up the macOS development phase in preparation for Linux integration testing. ## What Was Built / Changed ### Makefile (CL 32818 → 32821) Added in CL 32818 (previous session). Key targets: | Target | Purpose | |---|---| | `make build` | Current platform → `bin/p4lf` | | `make build-linux` | Linux amd64 → `bin/p4lf-linux-amd64` *(primary deploy target)* | | `make build-linux-arm64` | Linux arm64 | | `make build-darwin` / `build-darwin-amd64` | macOS builds | | `make build-all` | All four platforms | | `make check` | vet + fmt + test (CI gate) | | `make install INSTANCE=1` | Deploy binary + systemd unit to SDP paths | | `make release VERSION=x.y.z` | All platforms + `dist/` tarballs | ### Version stamping (CL 32819, 32820, 32821) `internal/version/version.go` is stored in Perforce as **type `text+k`**. Perforce expands three keywords on every submit/sync of this file: | Constant | Example after expansion | |---|---| | `P4ID` | `$Id: //p4lf/dev/internal/version/version.go#2 $` | | `P4Change` | `$Change: 32820 $` | | `P4DateTime` | `$DateTime: 2026/06/25 12:14:37 $` | `SemVer` is a hand-maintained `var` (`"0.1.0"`) that can also be overridden at build time: `make build VERSION=1.0.0`. **`p4lf -version` output:** ``` p4lf 0.1.0 (CL 32820, //p4lf/dev#2, 2026/06/25) ``` **Verifiable without running the binary:** ``` strings p4lf | grep 'Id:\|Change:\|DateTime:' ``` #### Key implementation detail: preventing regex expansion The regex patterns that parse the keyword values (e.g., `\$Id:\s*...`) must NOT themselves be expanded by Perforce. The fix: define `const dollar = "\x24"` (dollar sign in hex) and build patterns via string concatenation: ```go var idRe = regexp.MustCompile(`\` + dollar + `Id:\s*(//[^\s#]+)(#\d+)\s*\` + dollar) ``` P4 never sees `$Id:` as a contiguous byte sequence in the source, so it leaves the regex patterns alone. This was a bug in the first submit (CL 32819) and fixed in CL 32820. #### Makefile VERSION grep fix (CL 32821) The grep `SemVer\s*=` also matched the `-ldflags` example in the package doc comment, corrupting the VERSION value. Fixed by anchoring: `^var SemVer`. ## Current Depot State | CL | Description | |---|---| | 32818 | Initial Go implementation (all source files, Makefile, config, tailer, chunker, logger, systemd, example config, session logs) | | 32819 | Version stamping (version.go as text+k) — had regex expansion bug | | 32820 | Fix regex patterns with `const dollar = "\x24"` | | 32821 | Fix Makefile VERSION grep anchor | Latest: `//p4lf/dev` at CL 32821, all `make check` tests passing, all four platform binaries building cleanly. ## Testing Checklist for Linux Session The following should be verified on a Linux host with an SDP environment and running p4d instance: ### 1. Basic build ```bash go version # Confirm Go is available (1.20+ required) p4 sync # Sync workspace make build # Should produce bin/p4lf bin/p4lf -version # Should show: p4lf 0.1.0 (CL 32821, //p4lf/dev#N, ...) ``` ### 2. Config file ```bash cp p4lf.cfg.example /tmp/test-p4lf.cfg # Edit: set P4LogFile to your P4LOG path bin/p4lf -config /tmp/test-p4lf.cfg # Should start and log to /tmp/p4lf.log (since $LOGS not set) ``` ### 3. Chunk file creation - After one `LogTailDelay` interval, verify `log.*.gz` files appear in `LogChunksDir` - `gunzip -c log.*.gz | head` should show real P4LOG content ### 4. State file - Stop and restart the service - Verify offset is resumed (no duplicate chunks, no gap) - Check `$LOGS/p4lf.state` contains inode + offset JSON ### 5. Log rotation (inode-based detection) ```bash # Simulate a rotation while p4lf is running: mv $P4LOG $P4LOG.old && touch $P4LOG # p4lf should detect the inode change, log a rotation event, and reset to offset 0 ``` ### 6. SIGHUP ```bash kill -HUP $(pidof p4lf) # Should reload config and rotate p4lf.log ``` ### 7. systemd service ```bash sudo make install INSTANCE=1 # Edit /p4/common/site/log_feeder/p4lf.cfg sudo systemctl enable p4lf sudo systemctl start p4lf sudo systemctl status p4lf journalctl -u p4lf -f ``` ### 8. Graceful shutdown ```bash sudo systemctl stop p4lf # Should do final flush, write state, clean exit # Verify state file is current ``` ## Known Gaps / Items for Linux Session - **Tailer unit tests**: rotation detection, state file checkpoint/resume, and truncation handling are not unit-tested yet; rely on integration testing. - **Logger unit tests**: MaxLogSize trigger, gzip rotation not unit-tested. - **SDP environment file**: the systemd unit references `/p4/common/bin/p4_vars` for the `$LOGS` and `$P4LOG` env vars; verify this path is correct for the target SDP installation. - **`WaitUntilGuardsPassed` timeout**: currently waits indefinitely; may want a max-wait-and-warn after some number of retries. - **README.md**: not yet updated to reflect Go implementation and revised config.
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 32822 | C. Thomas Tyler | Session log 3: version stamping and Linux testing handoff. |