Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add semver tagging semantics #214

Merged
merged 36 commits into from
Nov 16, 2020
Merged

add semver tagging semantics #214

merged 36 commits into from
Nov 16, 2020

Conversation

vito
Copy link
Member

@vito vito commented Jun 22, 2020

fixes #151
closes #197 (supersedes it)

still a WIP - leaving lots of context in each commit message, will amend this with more commentary later

note: this is intended to be as backwards-compatible as possible, but the default behavior will change specifically when tag: is not specified. rather than tracking only the latest tag, the resource will track all semver tags present, only returning latest if there are no semver tags with the same digest

TODO:

  • /check: support detecting "variants" (i.e. alpine, 3-alpine, 3.2-alpine, 3.2.4-alpine)
  • /check: distinguish between multi-word variants (i.e. apache shouldn't match 1.2.3-foo-apache)
  • /check: distinguish between prereleases and variants (i.e. apache SHOULD match 1.2.3-rc.2-apache)
  • /check: skip prereleases by default, add flag
  • /check: support checking "from" a version
  • /check: refactor; there's a lot of branching with tag vs. non-tag and mirror vs. no mirror
  • /out: support pushing versions and variant versions
  • (bumping aliases #230): /out: implement optional semver tag bumping (i.e. bump 3.2, 3, and latest when shipping 3.2.4 assuming 3.2 is latest)
    • (bumping aliases #230) plus variant support (bump 3.2.0-alpine, and optionally 3.2-alpine if latest 3.2.x, 3-alpine if latest 3.x, alpine if latest overall)
  • update README
  • An initial check request which fetches digests of all the tags is a bit slow - it looks like go-containerregistry does a fresh auth flow for each call. Can we optimize this, either by avoiding requests when given a cursor version or by opening an issue on go-containerregistry? (opened issue: Is there a way to reuse token/transport to prevent repeated auth requests? google/go-containerregistry#740)
  • /in: respect a version that only has digest: - this is may be from a user manually pinning, per Feature request: support digest in 'source' #45 (comment)
    • hmm, actually maybe we should just always check and then find the specified version?

vito and others added 3 commits July 9, 2020 13:48
(this was probably from local hacking)

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
changes to /check:

* versions now include both tag and digest
* when tag: is omitted, detect tags based on semantic versioning
  * find all tags which are valid semver versions (e.g. 1, 1.2, 1.2.3)
    * skips any tags which aren't semver, except for 'latest' (see below)
  * for each semver tag found, emit each digest only once and in
    semver order, with most specific semver tag chosen
    * this prevents repeating 3, 3.2, 3.2.1 if they have the same
      digest; only 3.2.1 is returned instead
  * if 'latest' tag is present *and* has a unique digest, return it as
    the latest version
    * this is to support hotfixes or not strictly following semver for
      whatever reason; the intent is for 'latest' to be latest
    * if latest tag digest is also tagged as a semver tag, don't return
      it; it may be a race condition when pushing a new version (e.g.
      5.0.0 tagged but 'latest' not bumped yet)

changes to /in:

* now writes the tag from the given version to ./tag, rather than the
  tag: from source
* still fetches the exact digest from the version

/out is semantically unchanged, and only has refactors to deal with the
now-optional tag: field

TODO:

* implement checking from a cursor; currently just returns all versions
* support 'variants' i.e. 1.2.3-foo
* automatic tag bumping in /out

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
@vito vito force-pushed the semver-tags branch 2 times, most recently from 0c12207 to 6ad4a07 Compare July 9, 2020 18:01
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
vito and others added 9 commits July 9, 2020 14:20
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
note: we are following the future-looking resource check semantics here.
the initial check will return all versions. later checks will treat the
tag and digest as a cursor: as long as the digest is the same, only the
versions after the tag will be returned. if the digests differ, all
versions will be returned instead, "resetting" the history.

Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
instead of passing a bunch of values, just 'rewrite' the source config
to point to a mirror

Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Signed-off-by: Alex Suraci <asuraci@vmware.com>
Co-authored-by: James Thomson <jamesth@vmware.com>
vito added 3 commits July 16, 2020 10:42
this is a significant optimization: before we would fetch the digest for
every tag, now we'll only fetch the digest for the latest tag + any tags
with newer versions.

Signed-off-by: Alex Suraci <asuraci@vmware.com>
this will perform a ping + auth flow and then pass the transport along
in options for all subsequent requests.

the net effect is that rather than pinging + acquiring a token on every
request, we will only ping, since the token is already acquired. i'm not
sure if either of these endpoints are rate limited in the first place,
so this might not matter, but it at least saves time.

Signed-off-by: Alex Suraci <asuraci@vmware.com>
these needed tag: configured, but they were skipped because my local
test setup didn't have the docker image stuff set. that doesn't actually
need to be set for the 429 test, since they use a fake registry, so i
moved them to a separate context.

Signed-off-by: Alex Suraci <asuraci@vmware.com>
@vito
Copy link
Member Author

vito commented Jul 17, 2020

@xtreme-sameer-vohra Quick update: this is good to go! Just finished the last TODO item and fixed a broken test.

@vito
Copy link
Member Author

vito commented Sep 17, 2020

@xtreme-sameer-vohra I merged master into this instead of rebasing. There are a bunch of commits here so rebasing would have been a nightmarish hellscape vs. merging and resolving all the conflicts at once. Hope that's OK.

for posterity: this merge was done by basically choosing the #214 side
of every change and then just manually re-doing the changes.

this also includes some test cleanup around registry mirrors which I
mentioned doing in #248.

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
@vito vito marked this pull request as ready for review November 2, 2020 22:26
@vito
Copy link
Member Author

vito commented Nov 2, 2020

@xtreme-sameer-vohra This is ready to go again. We're thinking of jumping to v7.0 instead of v6.8 so I'd like to include this too since we're doing a major version bump and this involves a behaviour change, even though it's mostly backwards-compatible.

I wish I could make it easier to review but with how long this has been open it'd be a bit of a nightmare to rebase. All of my recent pushes are just to bring it in line with changes that have been made on master - mainly the registry mirror handling and the HEAD/GET fallback, and previously the whole commands/ restructuring. So hopefully there's not a whole lot to review from last time. 🙏

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
cmd/check/main.go Outdated Show resolved Hide resolved
@aoldershaw
Copy link
Contributor

Just skimmed through so far, but seems pretty nice!

Have you considered adding a semver constraint configuration to the source? Seems like it'd be super easy with Masterminds/semver

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
previously, if a 1.2.3-rc.4 tag was present alongside 1.2.3, the
resource would return 1.2.3-rc.4 as the tag. now it returns 1.2.3.

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
README.md Outdated Show resolved Hide resolved
Co-authored-by: Aidan Oldershaw <aoldershaw@pivotal.io>
Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
@vito
Copy link
Member Author

vito commented Nov 10, 2020

Have you considered adding a semver constraint configuration to the source? Seems like it'd be super easy with Masterminds/semver

Yeah I think that makes a lot of sense. I'd rather leave it for a separate PR though, just 'cause this one's pretty big already.

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
README.md Show resolved Hide resolved
also ensure tag is included when given a cursor version that doesn't
have the tag present, so that versions are consistent when given a
partial version with `fly check-resource --from`

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
@aoldershaw
Copy link
Contributor

aoldershaw commented Nov 12, 2020

check is certainly doing a lot more work, given that it has to make a HEAD request for each (semver) tag. I wanted to see how much slower it is:

$ jq -n '{source:{repository:"nginx"}}' | \
    time docker run --rm -i concourse/registry-image-resource:pr-alpine-214 \
      /opt/resource/check
...
       25.66 real         0.05 user         0.02 sys

compared to latest:

$ jq -n '{source:{repository:"nginx"}}' | \
    time docker run --rm -i concourse/registry-image-resource \
      /opt/resource/check
...
        1.53 real         0.05 user         0.02 sys

It's quite a bit slower. I expect this won't be a huge problem for named resources, since they only need to do this slow check once (and whenever a digest disappears) - but will it be for anonymous task.image_resources?

edit: obviously, "problem" is subjective - things will still work, but if it tacks on an extra 20s to many task steps, that could be a bit annoying

edit take 2: I refreshed my memory on how the check step works, and see that it uses the latest version based on the resource config scope if a from version isn't explicitly set - so this won't actually be slow for subsequent task runs, will it? (the whole resource config scope thing still kinda eludes me)

@vito
Copy link
Member Author

vito commented Nov 14, 2020

@aoldershaw Yup - that's what led to the whole image-fetching refactor. With how things used to work, it would definitely be too slow for task image resources - but now that check runs from the latest version, it should only be slow the first time the image is ever used.

Scopes are a little confusing, but in this case you can ignore them since scopes only apply to pipeline-level resources - otherwise it'll be the "null" (global) scope.

Copy link
Contributor

@aoldershaw aoldershaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@vito vito merged commit a40ca47 into master Nov 16, 2020
@vito vito deleted the semver-tags branch November 16, 2020 17:00
@vito vito added breaking enhancement New feature or request labels Nov 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Semver tags should be used for versions - not digests
4 participants