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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@ the SHA. This makes branch tags **sortable** so
newest build — the Git SHA alone is not orderable. The short SHA is kept for
traceability and Flux sorts on the timestamp only.

> **Note:** with `docker-tag-timestamp: 'true'` 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
> Flux ignores it.

With the timestamp enabled, use one `ImagePolicy` per environment, filtering by prefix:

```yaml
Expand Down
39 changes: 26 additions & 13 deletions scripts/generate-tags.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,34 @@ require_env INPUT_DOCKER_REGISTRY
require_env INPUT_DOCKER_IMAGE

BUILD="true"
# ALIAS_TAG is an additional immutable tag pushed alongside TAG (see set_branch_tags).
ALIAS_TAG=""

# branch_tag builds the immutable tag for an environment branch.
# 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 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. The SHA is kept
# for traceability. When the flag is unset/false the legacy <prefix>-<sha> shape
# is produced, so existing consumers are unaffected.
# 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.
# 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.
#
# The timestamp is overridable via BUILD_TIMESTAMP for deterministic tests.
branch_tag() {
set_branch_tags() {
local prefix="$1"
local sha="${GITHUB_SHA::8}"
if [[ "${INPUT_DOCKER_TAG_TIMESTAMP:-false}" == "true" ]]; then
local ts="${BUILD_TIMESTAMP:-$(date -u +%Y%m%d%H%M%S)}"
echo "${prefix}-${ts}-${GITHUB_SHA::8}"
TAG="${prefix}-${ts}-${sha}"
ALIAS_TAG="${prefix}-${sha}"
else
echo "${prefix}-${GITHUB_SHA::8}"
TAG="${prefix}-${sha}"
ALIAS_TAG=""
fi
}

Expand All @@ -43,15 +53,15 @@ if [[ -n "${INPUT_DOCKER_CUSTOM_TAG:-}" ]]; then
PUSH="true"
BUILD="${INPUT_DOCKER_DISABLE_RETAGGING:-false}"
elif [[ $GITHUB_REF == refs/heads/master ]]; then
TAG="$(branch_tag master)"
set_branch_tags master
LATEST="master"
PUSH="true"
elif [[ $GITHUB_REF == refs/heads/main ]]; then
TAG="$(branch_tag main)"
set_branch_tags main
LATEST="main"
PUSH="true"
elif [[ $GITHUB_REF == refs/heads/dev ]]; then
TAG="$(branch_tag dev)"
set_branch_tags dev
LATEST="dev"
PUSH="true"
elif [[ $GITHUB_REF == refs/tags/v* ]]; then
Expand All @@ -71,6 +81,9 @@ else
fi

TAG_LIST="${INPUT_DOCKER_REGISTRY}/${INPUT_DOCKER_IMAGE}:${TAG}"
if [[ -n "${ALIAS_TAG:-}" ]]; then
TAG_LIST+=",${INPUT_DOCKER_REGISTRY}/${INPUT_DOCKER_IMAGE}:${ALIAS_TAG}"
fi
if [[ -n "${LATEST:-}" ]]; then
TAG_LIST+=",${INPUT_DOCKER_REGISTRY}/${INPUT_DOCKER_IMAGE}:${LATEST}"
fi
Expand Down
21 changes: 21 additions & 0 deletions tests/generate-tags.bats
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,27 @@ teardown() {
assert_output_value "latest" "dev"
}

@test "timestamp flag pushes a stable <prefix>-<sha> alias in tag_list" {
export INPUT_DOCKER_TAG_TIMESTAMP="true"
export GITHUB_REF="refs/heads/main"
run "$SCRIPT"
assert_success
# canonical timestamped tag + stable sha alias (for release retag) + floating tag
local tag_list
tag_list=$(get_output_value "tag_list")
[[ "$tag_list" == "registry.staffbase.com/my-service:main-20260602143055-abcdef12,registry.staffbase.com/my-service:main-abcdef12,registry.staffbase.com/my-service:main" ]]
}

@test "no <prefix>-<sha> alias is added when timestamp flag is off" {
export GITHUB_REF="refs/heads/main"
run "$SCRIPT"
assert_success
local tag_list
tag_list=$(get_output_value "tag_list")
[[ "$tag_list" != *"my-service:main-abcdef12,"*"my-service:main-abcdef12"* ]]
[[ "$tag_list" == "registry.staffbase.com/my-service:main-abcdef12,registry.staffbase.com/my-service:main" ]]
}

@test "main branch with timestamp flag inserts timestamp before sha" {
export INPUT_DOCKER_TAG_TIMESTAMP="true"
export GITHUB_REF="refs/heads/main"
Expand Down
Loading