diff --git a/internal/e2e/gitlab/template_test.go b/internal/e2e/gitlab/template_test.go index 30bb0e9..53a8330 100644 --- a/internal/e2e/gitlab/template_test.go +++ b/internal/e2e/gitlab/template_test.go @@ -33,7 +33,8 @@ import ( // 1. the hub: the template's files in one commit, as GitLab's import of a // repository makes a project (no pipeline runs), in the group of hubs, // with the instance runners off; the one change is the image line, the -// TODO(release) placeholder replaced with the image under test, in the +// template's pin (a release's digest, or the TODO(release) placeholder +// before the first release) replaced with the image under test, in the // same NAME:TAG@sha256: form; // 2. `touchmark setup gitlab` from a clone of the hub, with the person's // token (README "On GitLab", steps 2 to 4); @@ -257,17 +258,19 @@ func templateFiles(tpl map[string][]byte, replace map[string]string) []conforman return files } -// placeholderImage is the template's image line before a release pins it. -var placeholderImage = regexp.MustCompile(`(?m)^(\s*name: )ghcr\.io/bedrock-python/touchmark:[^@\s]+@sha256:0{64}$`) +// templateImage is the template's touchmark image line: a release's, +// pinned by digest, or before the first release the TODO(release) +// placeholder, whose digest is all zeros. +var templateImage = regexp.MustCompile(`(?m)^(\s*name: )ghcr\.io/bedrock-python/touchmark:[^@\s]+@sha256:[0-9a-f]{64}$`) -// pinImage replaces the one placeholder image of the template's +// pinImage replaces the one touchmark image of the template's // .gitlab-ci.yml with image, as a release's update does. func pinImage(t *testing.T, ci, image string) string { t.Helper() - if n := len(placeholderImage.FindAllString(ci, -1)); n != 1 { - t.Fatalf("the template's .gitlab-ci.yml has %d placeholder image lines (name: ghcr.io/bedrock-python/touchmark:@sha256:0…), want 1", n) + if n := len(templateImage.FindAllString(ci, -1)); n != 1 { + t.Fatalf("the template's .gitlab-ci.yml has %d touchmark image lines (name: ghcr.io/bedrock-python/touchmark:@sha256:), want 1", n) } - return placeholderImage.ReplaceAllString(ci, "${1}"+image) + return templateImage.ReplaceAllString(ci, "${1}"+image) } // describeHub sets id and writer in the template's hub.yml, as README step diff --git a/internal/e2e/template_test.go b/internal/e2e/template_test.go index 537b650..db3a0a0 100644 --- a/internal/e2e/template_test.go +++ b/internal/e2e/template_test.go @@ -26,7 +26,8 @@ import ( // // 1. the hub: the template's files in one commit on main, as a migration // makes it (the commit skips CI), in the organisation of hubs; the one -// change is the image of the jobs, the TODO(release) placeholder +// change is the image of the jobs, the template's pin (a release's +// digest, or the TODO(release) placeholder before the first release) // replaced with the image under test in the same NAME:TAG@sha256 form; // the reader's and the writer's tokens as the Actions secrets // TOUCHMARK_READ_TOKEN and TOUCHMARK_WRITE_TOKEN (README "On Gitea or @@ -304,18 +305,19 @@ func templateFiles(tpl map[string][]byte, replace map[string]string) []conforman return files } -// placeholderImage is a job's image in the template before a release pins -// it. -var placeholderImage = regexp.MustCompile(`(?m)^(\s*image: )ghcr\.io/bedrock-python/touchmark:[^@\s]+@sha256:0{64}$`) +// templateImage is a job's touchmark image in the template: a release's, +// pinned by digest, or before the first release the TODO(release) +// placeholder, whose digest is all zeros. +var templateImage = regexp.MustCompile(`(?m)^(\s*image: )ghcr\.io/bedrock-python/touchmark:[^@\s]+@sha256:[0-9a-f]{64}$`) -// pinImages replaces every placeholder image of a workflow with image, as -// a release's update does; the workflow must have one per job. +// pinImages replaces every touchmark image of a workflow with image, as a +// release's update does; the workflow must have one per job. func pinImages(t *testing.T, name, workflow, image string) string { t.Helper() - if len(placeholderImage.FindAllString(workflow, -1)) == 0 { - t.Fatalf("%s has no placeholder image (image: ghcr.io/bedrock-python/touchmark:@sha256:0…)", name) + if len(templateImage.FindAllString(workflow, -1)) == 0 { + t.Fatalf("%s has no touchmark image (image: ghcr.io/bedrock-python/touchmark:@sha256:)", name) } - return placeholderImage.ReplaceAllString(workflow, "${1}"+image) + return templateImage.ReplaceAllString(workflow, "${1}"+image) } // describeHub sets id and writer in the template's hub.yml, as README step diff --git a/scripts/e2e/template-lib.sh b/scripts/e2e/template-lib.sh index 6750549..9bed72d 100644 --- a/scripts/e2e/template-lib.sh +++ b/scripts/e2e/template-lib.sh @@ -97,9 +97,16 @@ tpl_image() { tpl_pushed=localhost:$port/touchmark:0.0.0-e2e docker tag "$image" "$tpl_pushed" docker push -q "$tpl_pushed" >/dev/null || die "cannot push to the registry on localhost:$port" - digest=$(docker image inspect -f '{{range .RepoDigests}}{{println .}}{{end}}' "$tpl_pushed" | - sed -n "s|^localhost:$port/touchmark@\(sha256:[0-9a-f]\{64\}\)\$|\1|p" | head -n 1) - [ -n "$digest" ] || die "the pushed image has no digest of localhost:$port" + # The digest is the one the registry serves for the tag, not the one + # RepoDigests names: with the containerd image store, a multi-platform + # image pulled for one platform is pushed as that platform's manifest + # alone, while RepoDigests keeps the index's digest, which the registry + # then lacks (a runner that always pulls fails on it). + digest=$(docker exec "$tpl_registry" wget -S -q -O /dev/null \ + --header 'Accept: application/vnd.oci.image.index.v1+json, application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.docker.distribution.manifest.v2+json' \ + "http://127.0.0.1:$port/v2/touchmark/manifests/0.0.0-e2e" 2>&1 | + sed -n 's/^ *[Dd]ocker-[Cc]ontent-[Dd]igest: *\(sha256:[0-9a-f]\{64\}\).*$/\1/p' | head -n 1) + [ -n "$digest" ] || die "the registry on localhost:$port serves no digest for $tpl_pushed" tpl_image_ref=$tpl_pushed@$digest log "touchmark image: $image, as $tpl_image_ref ($(docker run --rm --entrypoint touchmark "$tpl_image_ref" version 2>&1 | head -n 1))" }