Added selective prerelease check to container images promotion pipeline (#18833)

Added selective prerelease check to container images promotion pipeline
This commit is contained in:
fheinecke
2022-12-06 20:03:51 +00:00
committed by GitHub
parent 296255f868
commit 29d18c9349
6 changed files with 167 additions and 18 deletions
+97 -1
View File
@@ -9320,6 +9320,22 @@ steps:
commands:
- '[ -n ${DRONE_TAG} ] || (echo ''DRONE_TAG is not set. Is the commit tagged?''
&& exit 1)'
- name: Record if tag ($DRONE_TAG) is prerelease
image: golang:1.18-alpine
commands:
- apk add git
- mkdir -pv "/tmp/repo"
- cd "/tmp/repo"
- git init
- git remote add origin ${DRONE_REMOTE_URL}
- git fetch origin --tags
- git checkout -qf "${DRONE_TAG}"
- mkdir -pv $(dirname "/go/vars/release-is-prerelease")
- cd "/tmp/repo/build.assets/tooling"
- go run ./cmd/check -tag $DRONE_TAG -check prerelease &> /dev/null || echo 'Version
is a prerelease' > "/go/vars/release-is-prerelease"
- printf 'Version is '; [ ! -f "/go/vars/release-is-prerelease" ] && printf 'not
'; echo 'a prerelease'
- name: Wait for docker
image: docker
commands:
@@ -9329,6 +9345,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- name: Wait for docker registry
image: alpine
commands:
@@ -9337,6 +9354,7 @@ steps:
!= "200" ]; do sleep 1; done'
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- name: Check out code
image: alpine/git:latest
commands:
@@ -9348,6 +9366,7 @@ steps:
- git checkout -qf "$DRONE_TAG"
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- name: Build major, minor, and full semvers
image: alpine
commands:
@@ -9362,6 +9381,7 @@ steps:
- echo $(cat "/go/var/full-version")
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- name: Assume ECR - staging AWS Role
image: amazon/aws-cli
commands:
@@ -9388,6 +9408,7 @@ steps:
path: /root/.aws
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- name: Assume ECR - production AWS Role
image: amazon/aws-cli
commands:
@@ -9415,6 +9436,7 @@ steps:
depends_on:
- Assume ECR - staging AWS Role
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- name: Pull teleport:v11-amd64 and push it to Local Registry
image: docker
commands:
@@ -9436,6 +9458,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -9463,6 +9486,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -9490,6 +9514,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -9583,6 +9608,10 @@ steps:
- name: Create manifest and push "teleport:major" to Quay
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- docker login -u="$QUAY_USERNAME" -p="$QUAY_PASSWORD" "quay.io"
- docker manifest create quay.io/gravitational/teleport:$(cat "/go/var/major-version")
--amend quay.io/gravitational/teleport:$(cat "/go/var/major-version")-amd64 --amend
@@ -9607,6 +9636,10 @@ steps:
- name: Create manifest and push "teleport:minor" to Quay
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- docker login -u="$QUAY_USERNAME" -p="$QUAY_PASSWORD" "quay.io"
- docker manifest create quay.io/gravitational/teleport:$(cat "/go/var/minor-version")
--amend quay.io/gravitational/teleport:$(cat "/go/var/minor-version")-amd64 --amend
@@ -9737,6 +9770,10 @@ steps:
- name: Create manifest and push "teleport:major" to ECR - production
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- apk add --no-cache aws-cli
- aws ecr-public get-login-password --region=us-east-1 | docker login -u="AWS" --password-stdin
public.ecr.aws
@@ -9760,6 +9797,10 @@ steps:
- name: Create manifest and push "teleport:minor" to ECR - production
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- apk add --no-cache aws-cli
- aws ecr-public get-login-password --region=us-east-1 | docker login -u="AWS" --password-stdin
public.ecr.aws
@@ -9826,6 +9867,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -9853,6 +9895,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -9880,6 +9923,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -9973,6 +10017,10 @@ steps:
- name: Create manifest and push "teleport-ent:major" to Quay
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- docker login -u="$QUAY_USERNAME" -p="$QUAY_PASSWORD" "quay.io"
- docker manifest create quay.io/gravitational/teleport-ent:$(cat "/go/var/major-version")
--amend quay.io/gravitational/teleport-ent:$(cat "/go/var/major-version")-amd64
@@ -9997,6 +10045,10 @@ steps:
- name: Create manifest and push "teleport-ent:minor" to Quay
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- docker login -u="$QUAY_USERNAME" -p="$QUAY_PASSWORD" "quay.io"
- docker manifest create quay.io/gravitational/teleport-ent:$(cat "/go/var/minor-version")
--amend quay.io/gravitational/teleport-ent:$(cat "/go/var/minor-version")-amd64
@@ -10130,6 +10182,10 @@ steps:
- name: Create manifest and push "teleport-ent:major" to ECR - production
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- apk add --no-cache aws-cli
- aws ecr-public get-login-password --region=us-east-1 | docker login -u="AWS" --password-stdin
public.ecr.aws
@@ -10153,6 +10209,10 @@ steps:
- name: Create manifest and push "teleport-ent:minor" to ECR - production
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- apk add --no-cache aws-cli
- aws ecr-public get-login-password --region=us-east-1 | docker login -u="AWS" --password-stdin
public.ecr.aws
@@ -10220,6 +10280,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -10257,6 +10318,10 @@ steps:
- name: Create manifest and push "teleport-ent:major-fips" to Quay
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- docker login -u="$QUAY_USERNAME" -p="$QUAY_PASSWORD" "quay.io"
- docker manifest create quay.io/gravitational/teleport-ent:$(cat "/go/var/major-version")-fips
--amend quay.io/gravitational/teleport-ent:$(cat "/go/var/major-version")-fips-amd64
@@ -10277,6 +10342,10 @@ steps:
- name: Create manifest and push "teleport-ent:minor-fips" to Quay
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- docker login -u="$QUAY_USERNAME" -p="$QUAY_PASSWORD" "quay.io"
- docker manifest create quay.io/gravitational/teleport-ent:$(cat "/go/var/minor-version")-fips
--amend quay.io/gravitational/teleport-ent:$(cat "/go/var/minor-version")-fips-amd64
@@ -10347,6 +10416,10 @@ steps:
- name: Create manifest and push "teleport-ent:major-fips" to ECR - production
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- apk add --no-cache aws-cli
- aws ecr-public get-login-password --region=us-east-1 | docker login -u="AWS" --password-stdin
public.ecr.aws
@@ -10366,6 +10439,10 @@ steps:
- name: Create manifest and push "teleport-ent:minor-fips" to ECR - production
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- apk add --no-cache aws-cli
- aws ecr-public get-login-password --region=us-east-1 | docker login -u="AWS" --password-stdin
public.ecr.aws
@@ -10425,6 +10502,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -10453,6 +10531,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -10481,6 +10560,7 @@ steps:
path: /var/run
depends_on:
- Verify build is tagged
- Record if tag ($DRONE_TAG) is prerelease
- Wait for docker
- Wait for docker registry
- Check out code
@@ -10574,6 +10654,10 @@ steps:
- name: Create manifest and push "teleport-operator:major" to Quay
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- docker login -u="$QUAY_USERNAME" -p="$QUAY_PASSWORD" "quay.io"
- docker manifest create quay.io/gravitational/teleport-operator:$(cat "/go/var/major-version")
--amend quay.io/gravitational/teleport-operator:$(cat "/go/var/major-version")-amd64
@@ -10598,6 +10682,10 @@ steps:
- name: Create manifest and push "teleport-operator:minor" to Quay
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- docker login -u="$QUAY_USERNAME" -p="$QUAY_PASSWORD" "quay.io"
- docker manifest create quay.io/gravitational/teleport-operator:$(cat "/go/var/minor-version")
--amend quay.io/gravitational/teleport-operator:$(cat "/go/var/minor-version")-amd64
@@ -10732,6 +10820,10 @@ steps:
- name: Create manifest and push "teleport-operator:major" to ECR - production
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- apk add --no-cache aws-cli
- aws ecr-public get-login-password --region=us-east-1 | docker login -u="AWS" --password-stdin
public.ecr.aws
@@ -10755,6 +10847,10 @@ steps:
- name: Create manifest and push "teleport-operator:minor" to ECR - production
image: docker
commands:
- printf "Prerelease "; ! [ -f /go/vars/release-is-prerelease ] && printf "not ";
printf "detected for version $DRONE_TAG, "; [ -f /go/vars/release-is-prerelease
] && echo "skipping" || echo "continuing"
- '[ -f /go/vars/release-is-prerelease ] && exit 0'
- apk add --no-cache aws-cli
- aws ecr-public get-login-password --region=us-east-1 | docker login -u="AWS" --password-stdin
public.ecr.aws
@@ -18318,6 +18414,6 @@ volumes:
temp: {}
---
kind: signature
hmac: be622374eb69d4a57e6880bd1056381affeb389593c45ee22a2868d7f898f349
hmac: 1319900bf879fab43d7dc10a89a0acb99d9a2e577a36ca6b28604d1b386e2540
...
+1
View File
@@ -305,6 +305,7 @@ func (p *Product) getBaseImage(arch string, version *ReleaseVersion, containerRe
ShellBaseValue: version.GetFullSemver().GetSemverValue(),
DisplayBaseValue: version.MajorVersion,
Arch: arch,
IsForFullSemver: true,
},
)
}
+38 -7
View File
@@ -51,8 +51,10 @@ func NewTagTrigger(branchMajorVersion string) *TriggerInfo {
},
SupportedVersions: []*ReleaseVersion{
{
MajorVersion: branchMajorVersion,
ShellVersion: "$DRONE_TAG",
MajorVersion: branchMajorVersion,
ShellVersion: "$DRONE_TAG",
// Omitted because it doesn't matter here - only the full semver will only be published (see Flags)
// ShellIsPrerelease: // ,
RelativeVersionName: "branch",
},
},
@@ -63,6 +65,9 @@ func NewTagTrigger(branchMajorVersion string) *TriggerInfo {
}
func NewPromoteTrigger(branchMajorVersion string) *TriggerInfo {
prereleaseFilePath := "/go/vars/release-is-prerelease"
shellVersion := "$DRONE_TAG"
promoteTrigger := triggerPromote
promoteTrigger.Target.Include = append(promoteTrigger.Target.Include, "promote-docker")
@@ -77,12 +82,14 @@ func NewPromoteTrigger(branchMajorVersion string) *TriggerInfo {
},
SupportedVersions: []*ReleaseVersion{
{
MajorVersion: branchMajorVersion,
ShellVersion: "$DRONE_TAG",
MajorVersion: branchMajorVersion,
ShellVersion: shellVersion,
// Truthy if the file exists, which indicates a prerelease. See `recordPrereleaseStatus`` for details.
ShellIsPrerelease: fmt.Sprintf("[ -f %s ]", prereleaseFilePath),
RelativeVersionName: "branch",
},
},
SetupSteps: []step{verifyTaggedStep()},
SetupSteps: []step{verifyTaggedStep(), recordPrereleaseStatus(shellVersion, prereleaseFilePath)},
}
}
@@ -106,8 +113,10 @@ func NewCronTrigger(latestMajorVersions []string) *TriggerInfo {
if len(latestMajorVersions) > 1 {
for i, majorVersion := range latestMajorVersions[1:] {
supportedVersions = append(supportedVersions, &ReleaseVersion{
MajorVersion: majorVersion,
ShellVersion: readCronShellVersionCommand(majorVersionVarBasePath, majorVersion),
MajorVersion: majorVersion,
ShellVersion: readCronShellVersionCommand(majorVersionVarBasePath, majorVersion),
// Omitted because it doesn't matter here - latest tags should always be built
// ShellIsPrerelease: // ,
RelativeVersionName: fmt.Sprintf("previous-version-%d", i+1),
SetupSteps: []step{getLatestSemverStep(majorVersion, majorVersionVarBasePath)},
})
@@ -150,6 +159,28 @@ func readCronShellVersionCommand(majorVersionDirectory, majorVersion string) str
return fmt.Sprintf("v$(cat '%s-%s')", majorVersionDirectory, majorVersion)
}
func recordPrereleaseStatus(shellVersion, recordFilePath string) step {
clonePath := "/tmp/repo"
commands := []string{
"apk add git",
}
commands = append(commands, cloneRepoCommands(clonePath, "${DRONE_TAG}")...)
commands = append(commands,
fmt.Sprintf("mkdir -pv $(dirname %q)", recordFilePath),
fmt.Sprintf("cd %q", path.Join(clonePath, "build.assets", "tooling")),
// If the tag is a prerelease, create a file who's existence shows that it is one
fmt.Sprintf("go run ./cmd/check -tag %s -check prerelease &> /dev/null || echo 'Version is a prerelease' > %q", shellVersion, recordFilePath),
fmt.Sprintf("printf 'Version is '; [ ! -f \"%s\" ] && printf 'not '; echo 'a prerelease'", recordFilePath),
)
return step{
// Note that Drone will evaluate certain variables (such as '${DRONE_TAG}') to their actual value in the step name
Name: fmt.Sprintf("Record if tag (%s) is prerelease", shellVersion),
Image: fmt.Sprintf("golang:%s-alpine", GoVersion),
Commands: commands,
}
}
// Drone triggers must all evaluate to "true" for a pipeline to be executed.
// As a result these pipelines are duplicated for each trigger.
// See https://docs.drone.io/pipeline/triggers/ for details.
+1 -7
View File
@@ -70,13 +70,7 @@ type ImageTag struct {
DisplayBaseValue string // Should be set to a human-readable version of ShellTag
Arch string
IsImmutable bool
}
func NewLatestTag() *ImageTag {
return &ImageTag{
ShellBaseValue: "latest",
DisplayBaseValue: "latest",
}
IsForFullSemver bool // True if the image tag contains a full semver
}
func (it *ImageTag) AppendString(s string) {
@@ -32,6 +32,7 @@ const (
type ReleaseVersion struct {
MajorVersion string // This is the major version of a given build. `SearchVersion` should match this when evaluated.
ShellVersion string // This value will be evaluated by the shell in the context of a Drone step
ShellIsPrerelease string // This value will be evaluated in a shell context to determine if a release version is a prerelease. Must be POSIX compliant and not rely on other external utilities.
RelativeVersionName string // The set of values for this should not change between major releases
SetupSteps []step // Version-specific steps that must be ran before executing build and push steps
}
@@ -272,6 +273,7 @@ func (rv *ReleaseVersion) getTagsForVersion(onlyBuildFullSemver bool) []*ImageTa
ShellBaseValue: semver.GetSemverValue(),
DisplayBaseValue: semver.Name,
IsImmutable: semver.IsImmutable,
IsForFullSemver: semver.IsFull,
})
}
+28 -3
View File
@@ -164,14 +164,16 @@ func GetPublicEcrPullRegistry() *ContainerRepo {
}
func (cr *ContainerRepo) buildSteps(buildStepDetails []*buildStepOutput, flags *TriggerFlags) []step {
// This is used to grab information that is (or at least should be by design) the same for all values in the slice
if len(buildStepDetails) == 0 {
return nil
}
sourceBuildStep := buildStepDetails[0]
steps := make([]step, 0)
// Tag and push, collecting the names of the tag/push steps and the images pushed.
imageTags := cr.BuildImageTags(buildStepDetails[0].Version, flags)
imageTags := cr.BuildImageTags(sourceBuildStep.Version, flags)
pushedImages := make(map[*ImageTag][]*Image, len(imageTags))
pushStepNames := make([]string, 0, len(buildStepDetails))
for _, buildStepDetail := range buildStepDetails {
@@ -189,8 +191,14 @@ func (cr *ContainerRepo) buildSteps(buildStepDetails []*buildStepOutput, flags *
multiarchImageTag := *imageTag
multiarchImageTag.Arch = ""
manifestImage := buildStepDetails[0].Product.ImageBuilder(cr, &multiarchImageTag)
manifestStepName := cr.createAndPushManifestStep(manifestImage, pushStepNames, pushedImages[imageTag])
steps = append(steps, manifestStepName)
manifestStep := cr.createAndPushManifestStep(manifestImage, pushStepNames, pushedImages[imageTag])
// Only create and push manifest for major and minor versions if the release version is not a prerelease
if !flags.ShouldOnlyPublishFullSemver && !imageTag.IsForFullSemver {
manifestStep.Commands = buildPrereleaseExclusionaryCommands(sourceBuildStep.Version, manifestStep.Commands)
}
steps = append(steps, manifestStep)
}
return steps
@@ -339,3 +347,20 @@ func buildImmutableSafeCommands(isImmutable bool, imageToCheck string, commandsT
commandToRun := strings.Join(commandsToRun, " && ")
return []string{fmt.Sprintf("%s && echo 'Found existing image, skipping' || (%s)", conditionalCommand, commandToRun)}
}
// Modifies a set of commands to only be ran if `version.ShellIsPrerelease` evaluates at runtiem to false.
func buildPrereleaseExclusionaryCommands(version *ReleaseVersion, commandsToRun []string) []string {
// If no check is defined, just pass the commands through without a check
if version.ShellIsPrerelease == "" {
return commandsToRun
}
checkCommands := []string{
fmt.Sprintf(`printf "Prerelease "; ! %s && printf "not "; printf "detected for version %s, "; %s && echo "skipping" || echo "continuing"`,
version.ShellIsPrerelease, version.ShellVersion, version.ShellIsPrerelease),
// This will cause the step to exit without error, allowing future steps to continue without killing the pipeline
fmt.Sprintf("%s && exit 0", version.ShellIsPrerelease),
}
return append(checkCommands, commandsToRun...)
}