Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,040 changes: 2,016 additions & 24 deletions .drone.yml

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -854,12 +854,13 @@ update-api-import-path:
# - build binaries with 'make release'
# - run `make tag` and use its output to 'git tag' and 'git push --tags'
.PHONY: update-tag
update-tag: TAG_REMOTE ?= origin
update-tag:
@test $(VERSION)
git tag $(GITTAG)
git tag api/$(GITTAG)
(cd e && git tag $(GITTAG) && git push origin $(GITTAG))
git push origin $(GITTAG) && git push origin api/$(GITTAG)
git push $(TAG_REMOTE) $(GITTAG) && git push $(TAG_REMOTE) api/$(GITTAG)

# build/webassets directory contains the web assets (UI) which get
# embedded in the teleport binary
Expand Down
2 changes: 2 additions & 0 deletions dronegen/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func kubernetesAssumeAwsRoleStep(s kubernetesRoleSettings) step {
return step{
Name: s.name,
Image: "amazon/aws-cli",
Pull: "if-not-exists",
Environment: map[string]value{
"AWS_ACCESS_KEY_ID": s.awsAccessKeyID,
"AWS_SECRET_ACCESS_KEY": s.awsSecretAccessKey,
Expand Down Expand Up @@ -125,6 +126,7 @@ func kubernetesUploadToS3Step(s kubernetesS3Settings) step {
return step{
Name: "Upload to S3",
Image: "amazon/aws-cli",
Pull: "if-not-exists",
Environment: map[string]value{
"AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"},
"AWS_REGION": {raw: s.region},
Expand Down
5 changes: 3 additions & 2 deletions dronegen/buildbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ func buildboxPipelineStep(buildboxName string, fips bool) step {
return step{
Name: "Build and push " + buildboxName,
Image: "docker",
Volumes: []volumeRef{volumeRefDocker, volumeRefAwsConfig},
Pull: "if-not-exists",
Volumes: []volumeRef{volumeRefAwsConfig, volumeRefDocker, volumeRefDockerConfig},
Commands: []string{
`apk add --no-cache make aws-cli`,
`chown -R $UID:$GID /go`,
Expand Down Expand Up @@ -101,7 +102,7 @@ func buildboxPipeline() pipeline {
// only on master for now; add the release branch name when forking a new release series.
p.Trigger = pushTriggerForBranch("master", "branch/*")
p.Workspace = workspace{Path: "/go/src/github.com/gravitational/teleport"}
p.Volumes = []volume{volumeDocker, volumeAwsConfig}
p.Volumes = []volume{volumeAwsConfig, volumeDocker, volumeDockerConfig}
p.Services = []service{
dockerService(),
}
Expand Down
42 changes: 29 additions & 13 deletions dronegen/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,25 @@ var (
Name: "awsconfig",
Path: "/root/.aws",
}

// volumeDockerConfig is a temporary volume for storing docker
// credentials for use with the Docker-in-Docker service we use
// to isolate the host machines docker daemon from the one used
// during the build. Mount this any time you use `volumeDocker`
//
// Drone claims to destroy the the temp volumes after a workflow
// has run, so it should be safe to write credentials etc.
volumeDockerConfig = volume{
Name: "dockerconfig",
Temp: &volumeTemp{},
}

// volumeRefDockerConfig is how you reference the docker config
// volume in a workflow step
volumeRefDockerConfig = volumeRef{
Name: "dockerconfig",
Path: "/root/.docker",
}
)

var buildboxVersion value
Expand Down Expand Up @@ -242,18 +261,6 @@ func dockerRegistryService() service {
}
}

// dockerVolumes returns a slice of volumes
// It includes the Docker socket volume by default, plus any extra volumes passed in
func dockerVolumes(v ...volume) []volume {
return append(v, volumeDocker)
}

// dockerVolumeRefs returns a slice of volumeRefs
// It includes the Docker socket volumeRef as a default, plus any extra volumeRefs passed in
func dockerVolumeRefs(v ...volumeRef) []volumeRef {
return append(v, volumeRefDocker)
}

// releaseMakefileTarget gets the correct Makefile target for a given arch/fips/centos combo
func releaseMakefileTarget(b buildType) string {
makefileTarget := fmt.Sprintf("release-%s", b.arch)
Expand Down Expand Up @@ -283,10 +290,16 @@ func waitForDockerStep() step {
return step{
Name: "Wait for docker",
Image: "docker",
Pull: "if-not-exists",
Commands: []string{
`timeout 30s /bin/sh -c 'while [ ! -S /var/run/docker.sock ]; do sleep 1; done'`,
`printenv DOCKERHUB_PASSWORD | docker login -u="$DOCKERHUB_USERNAME" --password-stdin`,
},
Volumes: []volumeRef{volumeRefDocker, volumeRefDockerConfig},
Environment: map[string]value{
"DOCKERHUB_USERNAME": {fromSecret: "DOCKERHUB_USERNAME"},
"DOCKERHUB_PASSWORD": {fromSecret: "DOCKERHUB_READONLY_TOKEN"},
},
Volumes: []volumeRef{volumeRefDocker},
}
}

Expand All @@ -295,6 +308,7 @@ func waitForDockerRegistryStep() step {
return step{
Name: "Wait for docker registry",
Image: "alpine",
Pull: "if-not-exists",
Commands: []string{
"apk add curl",
fmt.Sprintf(`timeout 30s /bin/sh -c 'while [ "$(curl -s -o /dev/null -w %%{http_code} http://%s/)" != "200" ]; do sleep 1; done'`, LocalRegistrySocket),
Expand All @@ -306,6 +320,7 @@ func verifyTaggedStep() step {
return step{
Name: "Verify build is tagged",
Image: "alpine:latest",
Pull: "if-not-exists",
Commands: []string{
"[ -n ${DRONE_TAG} ] || (echo 'DRONE_TAG is not set. Is the commit tagged?' && exit 1)",
},
Expand All @@ -317,6 +332,7 @@ func cloneRepoStep(clonePath, commit string) step {
return step{
Name: "Check out code",
Image: "alpine/git:latest",
Pull: "if-not-exists",
Commands: cloneRepoCommands(clonePath, commit),
}
}
Expand Down
2 changes: 1 addition & 1 deletion dronegen/container_image_products.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ func (p *Product) createBuildStep(arch string, version *ReleaseVersion, publicEc
step := step{
Name: p.GetBuildStepName(arch, version),
Image: "docker",
Volumes: dockerVolumeRefs(volumeRefAwsConfig),
Volumes: []volumeRef{volumeRefAwsConfig, volumeRefDocker}, // no docker config volume, as this will race
Environment: envVars,
Commands: commands,
DependsOn: getStepNames(publicEcrPullRegistry.SetupSteps),
Expand Down
2 changes: 1 addition & 1 deletion dronegen/container_images_release_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (rv *ReleaseVersion) buildVersionPipeline(triggerSetupSteps []step, flags *
dockerService(),
dockerRegistryService(),
}
pipeline.Volumes = dockerVolumes(volumeAwsConfig)
pipeline.Volumes = []volume{volumeAwsConfig, volumeDocker, volumeDockerConfig}
pipeline.Environment = map[string]value{
"DEBIAN_FRONTEND": {
raw: "noninteractive",
Expand Down
22 changes: 12 additions & 10 deletions dronegen/container_images_repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func NewEcrContainerRepo(accessKeyIDSecret, secretAccessKeySecret, roleSecret, d
loginCommands := []string{
"apk add --no-cache aws-cli",
fmt.Sprintf("aws %s get-login-password --region=%s | docker login -u=\"AWS\" --password-stdin %s", loginSubcommand, ecrRegion, domain),
`printenv DOCKERHUB_PASSWORD | docker login -u="$DOCKERHUB_USERNAME" --password-stdin`,
}

if guaranteeUnique {
Expand All @@ -72,7 +73,9 @@ func NewEcrContainerRepo(accessKeyIDSecret, secretAccessKeySecret, roleSecret, d
Name: repoName,
IsImmutable: isImmutable,
EnvironmentVars: map[string]value{
"AWS_PROFILE": {raw: profileName},
"AWS_PROFILE": {raw: profileName},
"DOCKERHUB_USERNAME": {fromSecret: "DOCKERHUB_USERNAME"},
"DOCKERHUB_PASSWORD": {fromSecret: "DOCKERHUB_READONLY_TOKEN"},
},
RegistryDomain: domain,
RegistryOrg: registryOrg,
Expand Down Expand Up @@ -112,17 +115,16 @@ func NewQuayContainerRepo(dockerUsername, dockerPassword string) *ContainerRepo
Name: "Quay",
IsImmutable: false,
EnvironmentVars: map[string]value{
"QUAY_USERNAME": {
fromSecret: dockerUsername,
},
"QUAY_PASSWORD": {
fromSecret: dockerPassword,
},
"QUAY_USERNAME": {fromSecret: dockerUsername},
"QUAY_PASSWORD": {fromSecret: dockerPassword},
"DOCKERHUB_USERNAME": {fromSecret: "DOCKERHUB_USERNAME"},
"DOCKERHUB_PASSWORD": {fromSecret: "DOCKERHUB_READONLY_TOKEN"},
},
RegistryDomain: ProductionRegistryQuay,
RegistryOrg: registryOrg,
LoginCommands: []string{
fmt.Sprintf("docker login -u=\"$QUAY_USERNAME\" -p=\"$QUAY_PASSWORD\" %q", ProductionRegistryQuay),
`printenv DOCKERHUB_PASSWORD | docker login -u="$DOCKERHUB_USERNAME" --password-stdin`,
},
}
}
Expand Down Expand Up @@ -254,7 +256,7 @@ func (cr *ContainerRepo) pullPushStep(image *Image, dependencySteps []string) (s
return step{
Name: fmt.Sprintf("Pull %s and push it to %s", image.GetDisplayName(), localRepo.Name),
Image: "docker",
Volumes: dockerVolumeRefs(volumeRefAwsConfig),
Volumes: []volumeRef{volumeRefAwsConfig, volumeRefDocker}, // no docker config volume, as this will race
Environment: cr.EnvironmentVars,
Commands: commands,
DependsOn: dependencySteps,
Expand Down Expand Up @@ -304,7 +306,7 @@ func (cr *ContainerRepo) tagAndPushStep(buildStepDetails *buildStepOutput, image
step := step{
Name: fmt.Sprintf("Tag and push image %q to %s", buildStepDetails.BuiltImage.GetDisplayName(), cr.Name),
Image: "docker",
Volumes: dockerVolumeRefs(volumeRefAwsConfig),
Volumes: []volumeRef{volumeRefAwsConfig, volumeRefDocker}, // no docker config volume, as this will race
Environment: cr.EnvironmentVars,
Commands: commands,
DependsOn: dependencySteps,
Expand Down Expand Up @@ -332,7 +334,7 @@ func (cr *ContainerRepo) createAndPushManifestStep(manifestImage *Image, pushSte
return step{
Name: fmt.Sprintf("Create manifest and push %q to %s", manifestImage.GetDisplayName(), cr.Name),
Image: "docker",
Volumes: dockerVolumeRefs(volumeRefAwsConfig),
Volumes: []volumeRef{volumeRefAwsConfig, volumeRefDocker}, // no docker config volume, as this will race
Environment: cr.EnvironmentVars,
Commands: cr.buildCommandsWithLogin(commands),
DependsOn: pushStepNames,
Expand Down
2 changes: 2 additions & 0 deletions dronegen/gha.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func ghaBuildPipeline(b ghaBuildType) pipeline {
{
Name: "Check out code",
Image: "docker:git",
Pull: "if-not-exists",
Environment: map[string]value{
"GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"},
},
Expand All @@ -49,6 +50,7 @@ func ghaBuildPipeline(b ghaBuildType) pipeline {
{
Name: "Delegate build to GitHub",
Image: fmt.Sprintf("golang:%s-alpine", GoVersion),
Pull: "if-not-exists",
Environment: map[string]value{
"GHA_APP_KEY": {fromSecret: "GITHUB_WORKFLOW_APP_PRIVATE_KEY"},
},
Expand Down
16 changes: 16 additions & 0 deletions dronegen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ func main() {
pipelines = append(pipelines, buildContainerImagePipelines()...)
pipelines = append(pipelines, publishReleasePipeline())

// Inject the Drone-level dockerhub credentials into all non-exec
// pipelines. Drone will then use the docker credentials file in
// the named secret as its credentials when pulling images from
// dockerhub.
//
// Exec pipelines do not have the `image_pull_secrets` option, as
// their steps are invoked directly on the host runner and not
// into a per-step container.
for pidx := range pipelines {
p := &pipelines[pidx]
if p.Type == "exec" {
continue
}
p.ImagePullSecrets = append(p.ImagePullSecrets, "DOCKERHUB_CREDENTIALS")
}

if err := writePipelines(".drone.yml", pipelines); err != nil {
fmt.Println("failed writing drone pipelines:", err)
os.Exit(1)
Expand Down
6 changes: 4 additions & 2 deletions dronegen/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,15 @@ func pushPipeline(b buildType) pipeline {
}
p.Trigger = triggerPush
p.Workspace = workspace{Path: "/go"}
p.Volumes = []volume{volumeDocker}
p.Volumes = []volume{volumeDocker, volumeDockerConfig}
p.Services = []service{
dockerService(),
}
p.Steps = []step{
{
Name: "Check out code",
Image: "docker:git",
Pull: "if-not-exists",
Environment: map[string]value{
"GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"},
},
Expand All @@ -139,8 +140,9 @@ func pushPipeline(b buildType) pipeline {
{
Name: "Build artifacts",
Image: "docker",
Pull: "if-not-exists",
Environment: pushEnvironment,
Volumes: []volumeRef{volumeRefDocker},
Volumes: []volumeRef{volumeRefDocker, volumeRefDockerConfig},
Commands: pushBuildCommands(b),
},
sendErrorToSlackStep(),
Expand Down
17 changes: 3 additions & 14 deletions dronegen/relcli.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,7 @@ func relcliPipeline(trigger trigger, name string, stepName string, command strin
}

p.Services = []service{dockerService(volumeRefTmpfs)}
p.Volumes = []volume{
volumeDocker,
volumeTmpfs,
volumeAwsConfig,
}
p.Volumes = []volume{volumeTmpfs, volumeAwsConfig, volumeDocker, volumeDockerConfig}

return p
}
Expand All @@ -60,10 +56,7 @@ func pullRelcliStep(awsConfigVolumeRef volumeRef) step {
Environment: map[string]value{
"AWS_DEFAULT_REGION": {raw: "us-west-2"},
},
Volumes: []volumeRef{
volumeRefDocker,
volumeRefAwsConfig,
},
Volumes: []volumeRef{volumeRefDocker, volumeRefAwsConfig},
Commands: []string{
`apk add --no-cache aws-cli`,
`aws ecr get-login-password | docker login -u="AWS" --password-stdin 146628656107.dkr.ecr.us-west-2.amazonaws.com`,
Expand All @@ -83,11 +76,7 @@ func executeRelcliStep(name string, command string) step {
"RELCLI_CERT": {raw: "/tmpfs/creds/releases.crt"},
"RELCLI_KEY": {raw: "/tmpfs/creds/releases.key"},
},
Volumes: []volumeRef{
volumeRefDocker,
volumeRefTmpfs,
volumeRefAwsConfig,
},
Volumes: []volumeRef{volumeRefDocker, volumeRefTmpfs, volumeRefAwsConfig},
Commands: []string{
`mkdir -p /tmpfs/creds`,
`echo "$RELEASES_CERT" | base64 -d > "$RELCLI_CERT"`,
Expand Down
14 changes: 8 additions & 6 deletions dronegen/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,15 @@ func tagPipeline(b buildType) pipeline {
p.Trigger = triggerTag
p.DependsOn = []string{tagCleanupPipelineName}
p.Workspace = workspace{Path: "/go"}
p.Volumes = []volume{volumeAwsConfig, volumeDocker}
p.Volumes = []volume{volumeAwsConfig, volumeDocker, volumeDockerConfig}
p.Services = []service{
dockerService(),
}
p.Steps = []step{
{
Name: "Check out code",
Image: "docker:git",
Pull: "if-not-exists",
Environment: map[string]value{
"GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"},
},
Expand All @@ -273,13 +274,15 @@ func tagPipeline(b buildType) pipeline {
{
Name: "Build artifacts",
Image: "docker",
Pull: "if-not-exists",
Environment: tagEnvironment,
Volumes: []volumeRef{volumeRefDocker},
Volumes: []volumeRef{volumeRefDocker, volumeRefDockerConfig},
Commands: tagBuildCommands(b),
},
{
Name: "Copy artifacts",
Image: "docker",
Pull: "if-not-exists",
Commands: tagCopyArtifactCommands(b),
},
kubernetesAssumeAwsRoleStep(kubernetesRoleSettings{
Expand All @@ -299,6 +302,7 @@ func tagPipeline(b buildType) pipeline {
{
Name: "Register artifacts",
Image: "docker",
Pull: "if-not-exists",
Commands: tagCreateReleaseAssetCommands(b, "", extraQualifications),
Environment: map[string]value{
"RELEASES_CERT": {fromSecret: "RELEASES_CERT"},
Expand Down Expand Up @@ -447,12 +451,10 @@ func tagPackagePipeline(packageType string, b buildType) pipeline {
environment["OSS_TARBALL_PATH"] = value{raw: "/go/artifacts"}
}

packageDockerVolumes := []volume{
volumeDocker,
volumeAwsConfig,
}
packageDockerVolumes := []volume{volumeAwsConfig, volumeDocker, volumeDockerConfig}
packageDockerVolumeRefs := []volumeRef{
volumeRefDocker,
volumeRefDockerConfig,
volumeRefAwsConfig,
}
packageDockerService := dockerService()
Expand Down
Loading