Enable Flag in Raw Tag does not work as expected
Contributing guidelines
- [x] I've read the contributing guidelines and wholeheartedly agree
I've found a bug, and:
- [x] The documentation does not mention anything about my problem
- [x] There are no open or closed issues that are related to my problem
Description
When using a raw tag with the enable flag, the tag is still in the metadata output when enable is set to false.
Expected behaviour
Run docker/metadata-action@v5
Context info
Processing images input
Processing tags input
type=semver,pattern={{raw}},value=v0.0.1+test,enable=true,priority=900
type=raw,value=latest,enable=false,priority=200
Processing flavor input
Docker image version
Docker tags
ghcr.io/{org}/{image}:v0.0.1-test
Docker labels
Annotations
JSON output
Bake file definition (tags)
Bake file definition (labels)
Bake file definition (annotations)
Actual behaviour
Run docker/metadata-action@v5
Context info
Processing images input
Processing tags input
type=semver,pattern={{raw}},value=v0.0.1+test,enable=true,priority=900
type=raw,value=latest,enable=false,priority=200
Processing flavor input
Docker image version
Docker tags
ghcr.io/{org}/{image}:v0.0.1-test
ghcr.io/{org}/{image}:latest
Docker labels
Annotations
JSON output
Bake file definition (tags)
Bake file definition (labels)
Bake file definition (annotations)
Repository URL
No response
Workflow run URL
No response
YAML workflow
- name: Docker Meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ needs.set-workflow-vars.outputs.image-name }}
tags: |
type=semver,pattern={{raw}},value=${{ needs.set-workflow-vars.outputs.version }}
type=raw,value=latest,enable=${{ inputs.is-latest }} # This input is typed as a boolean in the callable workflow, maybe that's it?
Workflow logs
Run docker/metadata-action@v5
Context info
Processing images input
Processing tags input
type=semver,pattern={{raw}},value=v0.0.1+test,enable=true,priority=900
type=raw,value=latest,enable=false,priority=200
Processing flavor input
Docker image version
Docker tags
ghcr.io/{org}/{image}:v0.0.1-test
ghcr.io/{org}/{image}:latest
Docker labels
Annotations
JSON output
Bake file definition (tags)
Bake file definition (labels)
Bake file definition (annotations)
BuildKit logs
No response
Additional info
No response
type=raw,value=latest,enable=${{ inputs.is-latest }}
Do you repro as well with type=raw,value=latest,enable=false? If not then that might be related to how GitHub handles boolean inputs.
type=raw,value=latest,enable=${{ inputs.is-latest }}Do you repro as well with
type=raw,value=latest,enable=false? If not then that might be related to how GitHub handles boolean inputs.
Yea that question is in the comment of the line where the bug originates from. It is a GHA typed boolean for sure. The peculiar thing is the fix I ended up going with.
Intsead of
- name: Docker Meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ needs.set-workflow-vars.outputs.image-name }}
tags: |
type=semver,pattern={{raw}},value=${{ needs.set-workflow-vars.outputs.version }}
type=raw,value=latest,enable=${{ inputs.is-latest }} # This input is typed as a boolean in the callable workflow, maybe that's it?
I ended up using the flavor input. Which is documented the same as tags as far as booleans go:
- name: Docker Meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ steps.set-vars.outputs.image-name }}
flavor: |
latest=${{ inputs.is-latest }}
tags: |
type=semver,pattern={{raw}},value=${{ inputs.version }}
Looks like this happened because you previously had the auto flavor paired with your semver type tag trigger:
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/meta.ts#L171-L186
At the start latest is initially false, and when the semver tag is considered a release tag it'll set that to true. Finally at the end of that snippet it'll check the latest flavor, which auto will use that latest=true that was set in the prior condition, otherwise it'll go based on the latest flavor set.
That's why your workaround to configure instead with flavor.latest worked 😎
It's a subtle bug that the README should probably highlight better, enable=false skips the tag processing, but for the latest tag itself you have to keep the default flavor behaviour in mind.
Additional context
Earlier in the process that semver type was processed here:
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/meta.ts#L46-L61
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/meta.ts#L66-L69
So the raw tag was in fact skipped due to your enabled=false, the caveat is latest was implicitly added regardless due to flavor.latest=auto + semver, which due to priority is processed first (even if priority was adjusted though, the enabled=false would skip setting version.latest=false, so you'd still get version.latest=true set once the semver tag is processed).
Tags are iterated through an array based on their priority:
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/tag.ts#L43-L52
If the raw tag had a higher priority (and was enabled) it'd have precedence at setting the latest tag to false:
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/meta.ts#L314-L317
latest is decided by the first tag to set it when it's in an undefined state:
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/meta.ts#L333
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/meta.ts#L343-L345
Comparison in source (not relevant)
latest:
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/flavor.ts#L4-L5
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/flavor.ts#L37-L42
enable:
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/tag.ts#L88-L99
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/tag.ts#L1
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/tag.ts#L203-L205
https://github.com/docker/metadata-action/blob/8e1d5461f02b7886d3c1a774bfbd873650445aa2/src/meta.ts#L53-L60
It's a subtle bug that the README should probably highlight better
I think a louder warning or an action failure when processing special case tags would better. Something that points to a corresponding readme section.
Just to clarify, you specifically mean with type=raw,value=latest,enable=false caveat with the default flavor.latest=auto?
I think there's other tag rules that could run into that latest tag issue depending on the setup, but the logic is a tad messy to sift through 😓 This is the most common combination I've seen though where the mishap happens.
Yea I think any tags that can be listed in the tags section whose behavior can be influenced by another setting should come with a warning if there are conflicting settings. I think just a quick lint or sanity check before attempting to run the action would be sufficient. I realize teasing out the edge cases could be tough, but the amount of time saved for devs would be worth it IMO. The iteration loop for CI jobs is loooooong, so being able to tighten up the feedback pays off in dividends.
I'm ultimately apathetic about it though as I rarely work on CI these days. Feel free to close this if you don't want to use it as a tracking issue.
I'm short on time, so here's a rough outline for anyone landing here, that may want to contribute a fix to the README:
-
type=rawcould mention a caveat withvalue=latest. - The
latesttag section references the defaultflavor.latest=autobehaviour.- That section then suggests using a
type=rawtag withenablefor controlling a conditionallatesttag, without clarifying that theflavor.latest=autodefault will disregard/override that enable logic. - Additionally if
flavor.latest=trueand atype=raw,value=latest,enable=truetag are both present, the tags output will produce twolatesttags (even when there is no suffix/prefix difference involved).
- That section then suggests using a
-
flavorsetting describes theonlatestcondition forflavor.<prefix|suffix>:-
It is not clarified that
onlatestattribute is only applicable to an implicitlatesttag generated fromflavor.latest=<auto|true>(whenautoresolves totrue).onlatesthas no relation to an explicittype=raw,value=latesttag (which could easily be confused that it does). -
onlatestis alsofalseby default, but that's not documented either (see this recent bug report from a confused user). -
flavor.suffix(and equivalentflavor.prefix) applies to all explicit tags, but can also be used as an attribute intagsto opt-out via,suffix=(suffix unset via an empty value). This override behaviour could be documented more clearly, given the current docs that show a tag types implicit defaults which already include,prefix=,suffix=it may not be obvious that you can opt-out of the flavor prefix/suffix this way.https://github.com/docker/metadata-action/blob/318604b99e75e41977312d83839a89be02ca4893/README.md?plain=1#L703-L708
-
Thanks for the convo and analysis on this issue! I will take a closer look