Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Whenever the action updates a GitOps file, it stamps the following annotations o
|------------|-------|
| `deploy.staffbase.com/repositoryFullName` | The source repository in `owner/repo` form (`$GITHUB_REPOSITORY`) |
| `deploy.staffbase.com/commitSha` | The commit SHA being deployed (`$GITHUB_SHA`) |
| `deploy.staffbase.com/version` | The deployed image tag — `dev-<short-sha>` on `dev`, `main-<short-sha>` on `main`, `master-<short-sha>` on `master` (with `docker-tag-timestamp` a UTC timestamp is inserted before the SHA), the version without the leading `v` on `v*` tag pushes, and the tag name on other tag pushes |
| `deploy.staffbase.com/version` | The deployed image tag — `dev-<timestamp>-<short-sha>` on `dev`, `main-<timestamp>-<short-sha>` on `main`, `master-<timestamp>-<short-sha>` on `master` (the UTC timestamp is inserted by default; with `docker-tag-timestamp: 'false'` it falls back to `<prefix>-<short-sha>`), the version without the leading `v` on `v*` tag pushes, and the tag name on other tag pushes |

These keys mirror the [Swarmia Deployment API](https://help.swarmia.com/settings/organization/configuring-deployments-in-swarmia) field names and are read by `flux-deployment-reporter` to report deployments to Swarmia once Flux finishes reconciling.

Expand All @@ -126,7 +126,7 @@ These keys mirror the [Swarmia Deployment API](https://help.swarmia.com/settings
| `docker-registry-api` | Docker Registry API (used for retagging without pulling) | `https://registry.staffbase.com/v2/` |
| `docker-image` | Docker Image | |
| `docker-custom-tag` | Docker Custom Tag to be set on the image | |
| `docker-tag-timestamp` | Insert a UTC timestamp into `dev`/`main`/`master` branch tags (`dev-<timestamp>-<short-sha>`) to make them sortable for Flux image automation | `false` |
| `docker-tag-timestamp` | Insert a UTC timestamp into `dev`/`main`/`master` branch tags (`dev-<timestamp>-<short-sha>`) to make them sortable for Flux image automation. Enabled by default; set to `'false'` for the legacy `<prefix>-<short-sha>` format | `true` |
| `docker-tag-keep-v-prefix` | Keep the leading `v` on release (`v*`) tags (`v1.2.3` → `v1.2.3`). Default strips it (`v1.2.3` → `1.2.3`) | `false` |
| `docker-username` | Username for the Docker Registry | |
| `docker-password` | Password for the Docker Registry | |
Expand Down Expand Up @@ -159,22 +159,22 @@ These keys mirror the [Swarmia Deployment API](https://help.swarmia.com/settings

The generated image tag depends on the Git ref:

| Ref | Tag (default) | Tag (`docker-tag-timestamp: 'true'`) | Floating tag |
| Ref | Tag (default) | Tag (`docker-tag-timestamp: 'false'`) | Floating tag |
|-----|---------------|--------------------------------------|--------------|
| `dev` branch | `dev-<short-sha>` | `dev-<utc-timestamp>-<short-sha>` | `dev` |
| `main` branch | `main-<short-sha>` | `main-<utc-timestamp>-<short-sha>` | `main` |
| `master` branch | `master-<short-sha>` | `master-<utc-timestamp>-<short-sha>` | `master` |
| `dev` branch | `dev-<utc-timestamp>-<short-sha>` | `dev-<short-sha>` | `dev` |
| `main` branch | `main-<utc-timestamp>-<short-sha>` | `main-<short-sha>` | `main` |
| `master` branch | `master-<utc-timestamp>-<short-sha>` | `master-<short-sha>` | `master` |
| `v*` tag (prod) | the version with the `v` stripped, e.g. `v2025.50.14` → `2025.50.14` (or kept with `docker-tag-keep-v-prefix: 'true'`) | _(unchanged)_ | `latest` |
| other branch | `<short-sha>` (not pushed) | _(unchanged)_ | — |

By default branch tags keep the legacy `<prefix>-<short-sha>` shape. Set
`docker-tag-timestamp: 'true'` to insert a `YYYYMMDDHHMMSS` (UTC) timestamp before
the SHA. This makes branch tags **sortable** so
By default branch tags carry a `YYYYMMDDHHMMSS` (UTC) timestamp inserted before the
SHA. This makes branch tags **sortable** so
[Flux image automation](https://fluxcd.io/flux/components/image/) can pick the
newest build — the Git SHA alone is not orderable. The short SHA is kept for
traceability and Flux sorts on the timestamp only.
traceability and Flux sorts on the timestamp only. Set `docker-tag-timestamp: 'false'`
to fall back to the legacy `<prefix>-<short-sha>` shape.

> **Note:** with `docker-tag-timestamp: 'true'` the build also pushes the plain
> **Note:** with the timestamp enabled (the default) the build also pushes the plain
> `<prefix>-<short-sha>` tag alongside the timestamped one. That stable per-commit
> tag is what the release step retags into the version tag, so it must continue
> to exist. It does not match the `^<prefix>-[0-9]+-[0-9a-f]+$` filter below, so
Expand Down
4 changes: 2 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ inputs:
description: 'Docker Custom Tag'
required: false
docker-tag-timestamp:
description: 'Insert a UTC timestamp into dev/main/master branch tags (e.g. dev-20260602143055-<short-sha>) to make them sortable for Flux image automation. Opt-in; defaults to the legacy <prefix>-<short-sha> format.'
description: 'Insert a UTC timestamp into dev/main/master branch tags (e.g. dev-20260602143055-<short-sha>) to make them sortable for Flux image automation. Enabled by default; set to ''false'' for the legacy <prefix>-<short-sha> format.'
required: false
default: 'false'
default: 'true'
docker-tag-keep-v-prefix:
description: 'Keep the leading "v" on release (v*) tags (v1.2.3 -> v1.2.3). Opt-in; defaults to stripping it (v1.2.3 -> 1.2.3).'
required: false
Expand Down
20 changes: 10 additions & 10 deletions scripts/generate-tags.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ ALIAS_TAG=""
# set_branch_tags computes the immutable tag(s) for an environment branch and
# assigns them to the globals TAG and ALIAS_TAG.
#
# When INPUT_DOCKER_TAG_TIMESTAMP is "true" the canonical TAG gets a UTC timestamp
# inserted before the short SHA (e.g. dev-20260602143055-abcdef12). This makes
# branch tags sortable by Flux image automation (numerical policy) — the Git SHA
# alone is not orderable, so Flux cannot otherwise tell which build is newest.
# In that case ALIAS_TAG holds the legacy <prefix>-<short-sha> tag, which is also
# pushed: it is the stable per-commit handle that retag-image.sh looks up to find
# the source image for a release, so dropping it would break the release retag.
# By default (INPUT_DOCKER_TAG_TIMESTAMP unset or "true") the canonical TAG gets a
# UTC timestamp inserted before the short SHA (e.g. dev-20260602143055-abcdef12).
# This makes branch tags sortable by Flux image automation (numerical policy) — the
# Git SHA alone is not orderable, so Flux cannot otherwise tell which build is
# newest. In that case ALIAS_TAG holds the legacy <prefix>-<short-sha> tag, which is
# also pushed: it is the stable per-commit handle that retag-image.sh looks up to
# find the source image for a release, so dropping it would break the release retag.
# The alias does not match Flux's "<prefix>-<digits>-<hex>" pattern, so Flux
# ignores it. When the flag is unset/false only the legacy <prefix>-<short-sha>
# tag is produced, so existing consumers are unaffected.
# ignores it. Set INPUT_DOCKER_TAG_TIMESTAMP="false" to opt out and produce only the
# legacy <prefix>-<short-sha> tag.
#
# The timestamp is overridable via BUILD_TIMESTAMP for deterministic tests.
set_branch_tags() {
local prefix="$1"
local sha="${GITHUB_SHA::8}"
if [[ "${INPUT_DOCKER_TAG_TIMESTAMP:-false}" == "true" ]]; then
if [[ "${INPUT_DOCKER_TAG_TIMESTAMP:-true}" == "true" ]]; then
local ts="${BUILD_TIMESTAMP:-$(date -u +%Y%m%d%H%M%S)}"
TAG="${prefix}-${ts}-${sha}"
ALIAS_TAG="${prefix}-${sha}"
Expand Down
39 changes: 31 additions & 8 deletions tests/generate-tags.bats
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ setup() {
export INPUT_DOCKER_IMAGE="my-service"
export INPUT_DOCKER_CUSTOM_TAG=""
export INPUT_DOCKER_DISABLE_RETAGGING="false"
# Timestamp suffix is opt-in; default off so the legacy <prefix>-<sha> format
# is the baseline. Tests that exercise the suffix set the flag explicitly.
# Timestamp suffix is on by default; leaving the flag unset exercises that
# default (the timestamped <prefix>-<ts>-<sha> format). Tests that need the
# legacy shape set the flag to "false" explicitly.
unset INPUT_DOCKER_TAG_TIMESTAMP
# Keeping the "v" prefix on release tags is opt-in; default off.
unset INPUT_DOCKER_TAG_KEEP_V_PREFIX
Expand All @@ -30,7 +31,7 @@ teardown() {
export GITHUB_REF="refs/heads/main"
run "$SCRIPT"
assert_success
assert_output_value "tag" "main-abcdef12"
assert_output_value "tag" "main-20260602143055-abcdef12"
assert_output_value "latest" "main"
assert_output_value "push" "true"
assert_output_value "build" "true"
Expand All @@ -42,7 +43,7 @@ teardown() {
export GITHUB_REF="refs/heads/master"
run "$SCRIPT"
assert_success
assert_output_value "tag" "master-abcdef12"
assert_output_value "tag" "master-20260602143055-abcdef12"
assert_output_value "latest" "master"
assert_output_value "push" "true"
assert_output_value "build" "true"
Expand All @@ -54,13 +55,13 @@ teardown() {
export GITHUB_REF="refs/heads/dev"
run "$SCRIPT"
assert_success
assert_output_value "tag" "dev-abcdef12"
assert_output_value "tag" "dev-20260602143055-abcdef12"
assert_output_value "latest" "dev"
assert_output_value "push" "true"
assert_output_value "build" "true"
}

# --- timestamp suffix (opt-in, Flux-sortable) ---
# --- timestamp suffix (default, Flux-sortable) ---

@test "dev branch with timestamp flag inserts timestamp before sha" {
export INPUT_DOCKER_TAG_TIMESTAMP="true"
Expand All @@ -83,6 +84,7 @@ teardown() {
}

@test "no <prefix>-<sha> alias is added when timestamp flag is off" {
export INPUT_DOCKER_TAG_TIMESTAMP="false"
export GITHUB_REF="refs/heads/main"
run "$SCRIPT"
assert_success
Expand Down Expand Up @@ -127,12 +129,33 @@ teardown() {
assert_output_value "tag" "2025.50.14"
}

@test "timestamp flag explicitly 'false' produces legacy shape" {
# --- legacy shape (timestamp explicitly off) ---

@test "dev branch with timestamp flag off produces legacy shape" {
export INPUT_DOCKER_TAG_TIMESTAMP="false"
export GITHUB_REF="refs/heads/dev"
run "$SCRIPT"
assert_success
assert_output_value "tag" "dev-abcdef12"
assert_output_value "latest" "dev"
}

@test "main branch with timestamp flag off produces legacy shape" {
export INPUT_DOCKER_TAG_TIMESTAMP="false"
export GITHUB_REF="refs/heads/main"
run "$SCRIPT"
assert_success
assert_output_value "tag" "main-abcdef12"
assert_output_value "latest" "main"
}

@test "master branch with timestamp flag off produces legacy shape" {
export INPUT_DOCKER_TAG_TIMESTAMP="false"
export GITHUB_REF="refs/heads/master"
run "$SCRIPT"
assert_success
assert_output_value "tag" "master-abcdef12"
assert_output_value "latest" "master"
}
# --- version tag ---

Expand Down Expand Up @@ -247,7 +270,7 @@ teardown() {
assert_success
local tag_list
tag_list=$(get_output_value "tag_list")
[[ "$tag_list" == "registry.staffbase.com/my-service:main-abcdef12,registry.staffbase.com/my-service:main" ]]
[[ "$tag_list" == "registry.staffbase.com/my-service:main-20260602143055-abcdef12,registry.staffbase.com/my-service:main-abcdef12,registry.staffbase.com/my-service:main" ]]
}

@test "tag_list has no latest suffix for feature branches" {
Expand Down
Loading