Open odormond opened 2 years ago
I'm running into something similar just using a simple resource not a resource-type. I'm not specifying a source.tag
in my resource and was surprised when my job ran with tag latest
. Since the documentation mentions:
With tag omitted, check will instead detect tags based on semver versions (e.g. 1.2.3) and return them in semver order
Note that this was a brand new pipeline so all the current images tags were all existing.
@odormond I have the impression that https://github.com/concourse/concourse/pull/8196 could be a manual workaround (until this issue is fixed).
@odormond I have the impression that concourse/concourse#8196 could be a manual workaround (until this issue is fixed).
Yes. That would be better than having to issue sql queries directly in the DB. :laughing:
We recently encountered an issue where the version of a resource type used by concourse was not the most recent one despite the fact that check correctly reported the most recent version available.
Here is the definition of the resource:
As you can see,
source.tag
is not set and we expect semver versioning of the resource type.Looking at the resource_config_versions table in the DB, here is what I saw:
As you can see:
latest
has the highestcheck_order
and so is considered the most recent versiondigest
of taglatest
is the same as the one of tag0.6.1
0.6.2
exists and is indeed more recent then0.6.1
Forcing a check prints out
0.6.2
as expected.After looking at the code, the problem can be explained as a race condition between tagging the repository images and checking them. Here is the scenario:
hash1
and tagslatest
and0.6.1
.latest
is processed and variablelatestTag
set and its digest stored intagDigests["latest"]
0.6.1
is processed anddigestVersions["hash1"]
is set to"0.6.1"
digestVersions
map is turned into the listtagVersions
which is then sortedresponse
is built fromtagVersions
latestTag
is set, its digest (hash1
) is looked up indigestVersions
and found and soexistsAsSemver
is true and soresponse
is left unchangedresponse
, which is[{"tag": "0.6.1", "digest": "hash1"}]
is returned0.6.2
only. Now it contains two images with hasheshash1
andhash2
.hash2
has tag0.6.2
andhash1
has the tags0.6.1
andlatest
.tags
is shuffled to put0.6.1
first becausefrom
is set to{"tag": "0.6.1", "digest": "hash1"}
by concourse following the previous check0.6.1
is processed,digestVersions["hash1"]
is set to"0.6.1"
andcursorVer
is set to"0.6.1"
latest
is processed and variablelatestTag
set and its digest stored intagDigests["latest"]
0.6.2
is processed anddigestVersions["hash2"]
is set to"0.6.2"
because it is greater than or equal tocursorVer
digestVersions
map is turned into the listtagVersions
which is then sortedresponse
is built fromtagVersions
latestTag
is set, its digest (hash1
) is looked up indigestVersions
and found and soexistsAsSemver
is true and soresponse
is left unchangedresponse
, which is[{"tag": "0.6.1", "digest": "hash1"}, {"tag": "0.6.2", "digest": "hash2"}]
is returnedtags
is shuffled to put0.6.2
first becausefrom
is set to{"tag": "0.6.2", "digest": "hash2"}
by concourse following the previous check0.6.2
is processed,digestVersions["hash2"]
is set to"0.6.2"
andcursorVer
is set to"0.6.2"
latest
is processed and variablelatestTag
set and its digest stored intagDigests["latest"]
0.6.1
is processed and ignored because it is less thancursorVer
digestVersions
map is turned into the listtagVersions
which is then sortedresponse
is built fromtagVersions
latestTag
is set, its digest (hash1
) is looked up indigestVersions
and not found and soexistsAsSemver
is false and soresponse
is extended with{"tag": "latest", "digest": "hash1"}
response
, which is now[{"tag": "0.6.2", "digest": "hash2"}, {"tag": "latest", "digest": "hash1"}]
is returned and so concourse now believes that{"tag": "latest", "digest": "hash1"}
is the most recent version, which is wronglatest
is moved to the image with tag0.6.2
and digesthash2
tags
is shuffled to putlatest
first becausefrom
is set to{"tag": "latest", "digest": "hash1"}
by concourse following the previous check, note that the digest infrom
is not actually thedigest
linked tolatest
in the registry nowlatest
is processed and variablelatestTag
set and its digest stored intagDigests["latest"]
0.6.2
is processed,digestVersions["hash2"]
is set to"0.6.2"
0.6.1
is processed,digestVersions["hash1"]
is set to"0.6.1"
digestVersions
has entries for both0.6.1
and0.6.2
becausecursorVer
is never set due to the fact thatfrom != nil && identifier == from.Tag && digest.String() == from.Digest
is never true, even whenidentifier
islatest
due to the fact that it'sdigest
ishash2
now butfrom.Digest
ishash1
digestVersions
map is turned into the listtagVersions
which is then sortedresponse
is built fromtagVersions
latestTag
is set, its digest (hash2
) is looked up indigestVersions
and found and soexistsAsSemver
is true and soresponse
left unchangedresponse
is now[{"tag": "0.6.1", "digest": "hash1"}, {"tag": "0.6.2", "digest": "hash2"}]
and so0.6.2
appears as the most recent version in the check output{"tag": "latest", "digest": "hash1"}
remains the most recent version