Use Kubernetes pod creation timestamp for deploy time in footer

- Read DEPLOY_TIMESTAMP environment variable for actual deploy time
- Fall back to compile time in development when env var not set
- Add Kubernetes Downward API to inject metadata.creationTimestamp
- Update k8s/deployment.yaml to set DEPLOY_TIMESTAMP env var
- Document deployment timestamp mechanism in k8s/README.md

This ensures the footer shows when the pod was deployed to the cluster,
not when the Docker image was built in CI/CD.
This commit is contained in:
Graham McIntire 2026-01-17 11:14:15 -06:00
parent ae16acf016
commit 9fcf19b304
No known key found for this signature in database
3 changed files with 53 additions and 5 deletions

View file

@ -12,6 +12,20 @@ Required secrets in the `towerops` namespace:
For local development, the project root `.envrc` is used by direnv.
## Deployment Timestamp
The application footer displays the deployment timestamp to track when the current version was deployed. This is automatically set using the Kubernetes Downward API:
```yaml
env:
- name: DEPLOY_TIMESTAMP
valueFrom:
fieldRef:
fieldPath: metadata.creationTimestamp
```
The pod's creation timestamp is injected as an environment variable and displayed in the footer as "Last deployed X ago · YYYY-MM-DD HH:MM:SS UTC".
## Deploying
Apply all resources using kustomize:

View file

@ -55,6 +55,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: DEPLOY_TIMESTAMP
valueFrom:
fieldRef:
fieldPath: metadata.creationTimestamp
- name: RELEASE_DISTRIBUTION
value: "name"
- name: RELEASE_NODE

View file

@ -5,7 +5,7 @@ defmodule Towerops.Application do
use Application
# Capture the build/deploy timestamp at compile time
# Capture the build timestamp at compile time (fallback for development)
@build_timestamp DateTime.utc_now()
@impl true
@ -49,11 +49,41 @@ defmodule Towerops.Application do
end
@doc """
Returns the build/deploy timestamp.
Returns the deployment timestamp.
This timestamp is captured at compile time and represents when the
application was last built/deployed.
In production (Kubernetes), this reads from the DEPLOY_TIMESTAMP environment
variable which should be set during deployment. Falls back to compile time
in development.
Set DEPLOY_TIMESTAMP in your Kubernetes deployment:
```yaml
env:
- name: DEPLOY_TIMESTAMP
value: "2026-01-17T12:34:56Z"
```
Or use a downward API to inject the pod creation time:
```yaml
env:
- name: DEPLOY_TIMESTAMP
valueFrom:
fieldRef:
fieldPath: metadata.creationTimestamp
```
"""
@spec build_timestamp() :: DateTime.t()
def build_timestamp, do: @build_timestamp
def build_timestamp do
case System.get_env("DEPLOY_TIMESTAMP") do
nil ->
# Development/fallback: use compile time
@build_timestamp
timestamp_string ->
# Production: parse from environment variable
case DateTime.from_iso8601(timestamp_string) do
{:ok, datetime, _offset} -> datetime
{:error, _} -> @build_timestamp
end
end
end
end