From fadcdaf6ea244c7e4e79964666db187543319bf5 Mon Sep 17 00:00:00 2001 From: Russell Jones Date: Fri, 17 Dec 2021 04:36:24 +0000 Subject: [PATCH] Remove dronegen from Teleport 8. Several hacks had to be introduced to support CentOS 7 in the Teleport 8 build/publish pipeline. Remove dronegen to prevent accidental reversion of this logic. --- Makefile | 5 - dronegen/buildbox.go | 86 --------- dronegen/common.go | 150 --------------- dronegen/cron.go | 20 -- dronegen/drone_cli.go | 42 ----- dronegen/mac.go | 279 --------------------------- dronegen/mac_pkg.go | 135 -------------- dronegen/main.go | 137 -------------- dronegen/misc.go | 25 --- dronegen/push.go | 153 --------------- dronegen/tag.go | 424 ------------------------------------------ dronegen/tests.go | 278 --------------------------- dronegen/types.go | 212 --------------------- 13 files changed, 1946 deletions(-) delete mode 100644 dronegen/buildbox.go delete mode 100644 dronegen/common.go delete mode 100644 dronegen/cron.go delete mode 100644 dronegen/drone_cli.go delete mode 100644 dronegen/mac.go delete mode 100644 dronegen/mac_pkg.go delete mode 100644 dronegen/main.go delete mode 100644 dronegen/misc.go delete mode 100644 dronegen/push.go delete mode 100644 dronegen/tag.go delete mode 100644 dronegen/tests.go delete mode 100644 dronegen/types.go diff --git a/Makefile b/Makefile index e9140542c01c6..d2b41cc1f2402 100644 --- a/Makefile +++ b/Makefile @@ -920,8 +920,3 @@ update-webassets: WEBAPPS_BRANCH ?= 'master' update-webassets: TELEPORT_BRANCH ?= 'master' update-webassets: build.assets/webapps/update-teleport-webassets.sh -w $(WEBAPPS_BRANCH) -t $(TELEPORT_BRANCH) - -# dronegen generates .drone.yml config -.PHONY: dronegen -dronegen: - go run ./dronegen diff --git a/dronegen/buildbox.go b/dronegen/buildbox.go deleted file mode 100644 index da00532254b8b..0000000000000 --- a/dronegen/buildbox.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import "fmt" - -func buildboxPipelineSteps() []step { - steps := []step{ - { - Name: "Check out code", - Image: "docker:git", - Commands: []string{ - `git clone --depth 1 --single-branch --branch ${DRONE_SOURCE_BRANCH:-master} https://github.com/gravitational/${DRONE_REPO_NAME}.git .`, - `git checkout ${DRONE_COMMIT}`, - }, - }, - waitForDockerStep(), - } - - for _, name := range []string{"buildbox", "buildbox-centos6", "buildbox-arm"} { - for _, fips := range []bool{false, true} { - // FIPS is unsupported on ARM/ARM64 - if name == "buildbox-arm" && fips { - continue - } - // FIPS is unsupported on CentOS 6 as of Teleport 7.0 - // https://github.com/gravitational/teleport/issues/7207 - if name == "buildbox-centos6" && fips { - continue - } - steps = append(steps, buildboxPipelineStep(name, fips)) - } - } - return steps -} - -func buildboxPipelineStep(buildboxName string, fips bool) step { - if fips { - buildboxName += "-fips" - } - return step{ - Name: buildboxName, - Image: "docker", - Environment: map[string]value{ - "QUAYIO_DOCKER_USERNAME": {fromSecret: "QUAYIO_DOCKER_USERNAME"}, - "QUAYIO_DOCKER_PASSWORD": {fromSecret: "QUAYIO_DOCKER_PASSWORD"}, - }, - Volumes: dockerVolumeRefs(), - Commands: []string{ - `apk add --no-cache make`, - `chown -R $UID:$GID /go`, - `docker login -u="$$QUAYIO_DOCKER_USERNAME" -p="$$QUAYIO_DOCKER_PASSWORD" quay.io`, - fmt.Sprintf(`make -C build.assets %s`, buildboxName), - fmt.Sprintf(`docker push quay.io/gravitational/teleport-%s:$RUNTIME`, buildboxName), - }, - } -} - -func buildboxPipeline() pipeline { - p := newKubePipeline("build-buildboxes") - p.Environment = map[string]value{ - "RUNTIME": goRuntime, - "UID": {raw: "1000"}, - "GID": {raw: "1000"}, - } - p.Trigger = triggerPushMasterOnly - p.Workspace = workspace{Path: "/go/src/github.com/gravitational/teleport"} - p.Volumes = dockerVolumes() - p.Services = []service{ - dockerService(), - } - p.Steps = buildboxPipelineSteps() - return p -} diff --git a/dronegen/common.go b/dronegen/common.go deleted file mode 100644 index ff6ee3c2c8f2a..0000000000000 --- a/dronegen/common.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "bytes" - "fmt" - "log" - "os/exec" -) - -var ( - triggerPullRequest = trigger{ - Event: triggerRef{Include: []string{"pull_request"}}, - Repo: triggerRef{Include: []string{"gravitational/*"}}, - } - triggerPush = trigger{ - Event: triggerRef{Include: []string{"push"}, Exclude: []string{"pull_request"}}, - Branch: triggerRef{Include: []string{"master", "branch/*"}}, - Repo: triggerRef{Include: []string{"gravitational/*"}}, - } - triggerTag = trigger{ - Event: triggerRef{Include: []string{"tag"}}, - Ref: triggerRef{Include: []string{"refs/tags/v*"}}, - Repo: triggerRef{Include: []string{"gravitational/*"}}, - } - triggerPushMasterOnly = trigger{ - Event: triggerRef{Include: []string{"push"}}, - Branch: triggerRef{Include: []string{"master"}}, - Repo: triggerRef{Include: []string{"gravitational/teleport"}}, - } - - volumeDocker = volume{ - Name: "dockersock", - Temp: &volumeTemp{}, - } - volumeDockerTmpfs = volume{ - Name: "dockertmpfs", - Temp: &volumeTemp{}, - } - volumeTmpfs = volume{ - Name: "tmpfs", - Temp: &volumeTemp{Medium: "memory"}, - } - volumeTmpIntegration = volume{ - Name: "tmp-integration", - Temp: &volumeTemp{}, - } - - volumeRefTmpfs = volumeRef{ - Name: "tmpfs", - Path: "/tmpfs", - } - volumeRefDocker = volumeRef{ - Name: "dockersock", - Path: "/var/run", - } - volumeRefDockerTmpfs = volumeRef{ - Name: "dockertmpfs", - Path: "/var/lib/docker", - } - volumeRefTmpIntegration = volumeRef{ - Name: "tmp-integration", - Path: "/tmp", - } -) - -var goRuntime value - -func init() { - v, err := exec.Command("make", "-s", "-C", "build.assets", "print-go-version").Output() - if err != nil { - log.Fatalf("could not get Go version: %v", err) - } - goRuntime = value{raw: string(bytes.TrimSpace(v))} -} - -type buildType struct { - os string - arch string - fips bool - centos6 bool - centos7 bool - windowsUnsigned bool -} - -// dockerService generates a docker:dind service -// It includes the Docker socket volume by default, plus any extra volumes passed in -func dockerService(v ...volumeRef) service { - return service{ - Name: "Start Docker", - Image: "docker:dind", - Privileged: true, - Volumes: append(v, volumeRefDocker), - } -} - -// 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) - if b.centos6 { - makefileTarget += "-centos6" - } else if b.centos7 { - makefileTarget += "-centos7" - } - if b.fips { - makefileTarget += "-fips" - } - if b.os == "windows" && b.windowsUnsigned { - makefileTarget = "release-windows-unsigned" - } - return makefileTarget -} - -// waitForDockerStep returns a step which checks that the Docker socket is active before trying -// to run container operations -func waitForDockerStep() step { - return step{ - Name: "Wait for docker", - Image: "docker", - Commands: []string{ - `timeout 30s /bin/sh -c 'while [ ! -S /var/run/docker.sock ]; do sleep 1; done'`, - }, - Volumes: dockerVolumeRefs(), - } -} diff --git a/dronegen/cron.go b/dronegen/cron.go deleted file mode 100644 index 37b40cb87661d..0000000000000 --- a/dronegen/cron.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -func cronPipelines() []pipeline { - // TODO: migrate - return nil -} diff --git a/dronegen/drone_cli.go b/dronegen/drone_cli.go deleted file mode 100644 index b0446bf4072e5..0000000000000 --- a/dronegen/drone_cli.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "fmt" - "os" - "os/exec" -) - -func checkDroneCLI() error { - if _, err := exec.LookPath("drone"); err != nil { - return fmt.Errorf("can't find drone CLI in $PATH: %w; get it from https://docs.drone.io/cli/install/", err) - } - if os.Getenv("DRONE_SERVER") == "" || os.Getenv("DRONE_TOKEN") == "" { - return fmt.Errorf("$DRONE_SERVER and/or $DRONE_TOKEN env vars not set; get them at https://drone.gravitational.io/account") - } - return nil -} - -func signDroneConfig() error { - out, err := exec.Command("drone", "sign", "gravitational/teleport", "--save").CombinedOutput() - if err != nil { - if len(out) > 0 { - err = fmt.Errorf("drone signing failed: %v\noutput:\n%s", err, out) - } - return err - } - return nil -} diff --git a/dronegen/mac.go b/dronegen/mac.go deleted file mode 100644 index da0e9cf69d021..0000000000000 --- a/dronegen/mac.go +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "fmt" - "path" -) - -// escapedPreformatted returns expr wrapped in escaped backticks, -// resulting in Slack "preformatted" string, but safe to use in bash -// without triggering the command expansion. -// This is useful for use in Go backtick literals, -// where backticks can not be escaped in any way. -func escapedPreformatted(expr string) string { - return fmt.Sprintf("\\`%s\\`", expr) -} - -func newDarwinPipeline(name string) pipeline { - p := newExecPipeline(name) - p.Workspace.Path = path.Join("/tmp", name) - p.Concurrency.Limit = 1 - p.Platform = platform{OS: "darwin", Arch: "amd64"} - return p -} - -func darwinPushPipeline() pipeline { - p := newDarwinPipeline("push-build-darwin-amd64") - p.Trigger = triggerPush - p.Steps = []step{ - setUpExecStorageStep(p.Workspace.Path), - { - Name: "Check out code", - Environment: map[string]value{ - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - "GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"}, - }, - Commands: pushCheckoutCommandsDarwin(), - }, - installGoToolchainStep(), - installRustToolchainStep(p.Workspace.Path), - { - Name: "Build Mac artifacts", - Environment: map[string]value{ - "GOPATH": {raw: path.Join(p.Workspace.Path, "/go")}, - "GOCACHE": {raw: path.Join(p.Workspace.Path, "/go/cache")}, - "OS": {raw: "darwin"}, - "ARCH": {raw: "amd64"}, - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - }, - Commands: darwinTagBuildCommands(), - }, - cleanUpToolchainsStep(p.Workspace.Path), - cleanUpExecStorageStep(p.Workspace.Path), - { - Name: "Send Slack notification (exec)", - Environment: map[string]value{"SLACK_WEBHOOK_DEV_TELEPORT": {fromSecret: "SLACK_WEBHOOK_DEV_TELEPORT"}}, - Commands: []string{ - ` -export DRONE_BUILD_LINK="${DRONE_SYSTEM_PROTO}://${DRONE_SYSTEM_HOSTNAME}/${DRONE_REPO_OWNER}/${DRONE_REPO_NAME}/${DRONE_BUILD_NUMBER}" -export GOOS=$(go env GOOS) -export GOARCH=$(go env GOARCH) -`, - fmt.Sprintf(` -curl -sL -X POST -H 'Content-type: application/json' --data "{\"text\":\"Warning: %s artifact build failed for [%s] - please investigate immediately!\nBranch: %s\nCommit: %s\nLink: $DRONE_BUILD_LINK\"}" $SLACK_WEBHOOK_DEV_TELEPORT`, - escapedPreformatted("${GOOS}-${GOARCH}"), - escapedPreformatted("${DRONE_REPO_NAME}"), - escapedPreformatted("${DRONE_BRANCH}"), - escapedPreformatted("${DRONE_COMMIT_SHA}")), - }, - When: &condition{Status: []string{"failure"}}, - }, - } - return p -} - -func darwinTagPipeline() pipeline { - p := newDarwinPipeline("build-darwin-amd64") - p.Trigger = triggerTag - p.Steps = []step{ - setUpExecStorageStep(p.Workspace.Path), - { - Name: "Check out code", - Environment: map[string]value{ - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - "GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"}, - }, - Commands: darwinTagCheckoutCommands(), - }, - installGoToolchainStep(), - installRustToolchainStep(p.Workspace.Path), - { - Name: "Build Mac release artifacts", - Environment: map[string]value{ - "GOPATH": {raw: path.Join(p.Workspace.Path, "/go")}, - "GOCACHE": {raw: path.Join(p.Workspace.Path, "/go/cache")}, - "OS": {raw: "darwin"}, - "ARCH": {raw: "amd64"}, - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - }, - Commands: darwinTagBuildCommands(), - }, - { - Name: "Copy Mac artifacts", - Environment: map[string]value{ - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - }, - Commands: darwinTagCopyPackageArtifactCommands(), - }, - { - Name: "Upload to S3", - Environment: map[string]value{ - "AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"}, - "AWS_ACCESS_KEY_ID": {fromSecret: "AWS_ACCESS_KEY_ID"}, - "AWS_SECRET_ACCESS_KEY": {fromSecret: "AWS_SECRET_ACCESS_KEY"}, - "AWS_REGION": {raw: "us-west-2"}, - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - }, - Commands: darwinUploadToS3Commands(), - }, - cleanUpToolchainsStep(p.Workspace.Path), - cleanUpExecStorageStep(p.Workspace.Path), - } - return p -} - -func pushCheckoutCommandsDarwin() []string { - return []string{ - `set -u`, - `mkdir -p $WORKSPACE_DIR/go/src/github.com/gravitational/teleport`, - `cd $WORKSPACE_DIR/go/src/github.com/gravitational/teleport`, - `git clone https://github.com/gravitational/${DRONE_REPO_NAME}.git .`, - `git checkout ${DRONE_TAG:-$DRONE_COMMIT}`, - // fetch enterprise submodules - // suppressing the newline on the end of the private key makes git operations fail on MacOS - // with an error like 'Load key "/path/.ssh/id_rsa": invalid format' - `mkdir -m 0700 $WORKSPACE_DIR/.ssh && echo "$GITHUB_PRIVATE_KEY" > $WORKSPACE_DIR/.ssh/id_rsa && chmod 600 $WORKSPACE_DIR/.ssh/id_rsa`, - `ssh-keyscan -H github.com > $WORKSPACE_DIR/.ssh/known_hosts 2>/dev/null`, - `chmod 600 $WORKSPACE_DIR/.ssh/known_hosts`, - `GIT_SSH_COMMAND='ssh -i $WORKSPACE_DIR/.ssh/id_rsa -o UserKnownHostsFile=$WORKSPACE_DIR/.ssh/known_hosts -F /dev/null' git submodule update --init e`, - // this is allowed to fail because pre-4.3 Teleport versions don't use the webassets submodule - `GIT_SSH_COMMAND='ssh -i $WORKSPACE_DIR/.ssh/id_rsa -o UserKnownHostsFile=$WORKSPACE_DIR/.ssh/known_hosts -F /dev/null' git submodule update --init --recursive webassets || true`, - `rm -rf $WORKSPACE_DIR/.ssh`, - `mkdir -p $WORKSPACE_DIR/go/cache`, - } -} - -func setUpExecStorageStep(path string) step { - return step{ - Name: "Set up exec runner storage", - Environment: map[string]value{"WORKSPACE_DIR": {raw: path}}, - Commands: []string{ - "set -u", - "mkdir -p $WORKSPACE_DIR", - "chmod -R u+rw $WORKSPACE_DIR", - "rm -rf $WORKSPACE_DIR/go $WORKSPACE_DIR/.ssh", - }, - } -} - -func installGoToolchainStep() step { - return step{ - Name: "Install Go Toolchain", - Environment: map[string]value{ - "RUNTIME": goRuntime, - }, - Commands: []string{ - `set -u`, - `mkdir -p ~/build-$DRONE_BUILD_NUMBER-$DRONE_BUILD_CREATED-toolchains`, - `curl --silent -O https://dl.google.com/go/$RUNTIME.darwin-amd64.tar.gz`, - `tar -C ~/build-$DRONE_BUILD_NUMBER-$DRONE_BUILD_CREATED-toolchains -xzf $RUNTIME.darwin-amd64.tar.gz`, - `rm -rf $RUNTIME.darwin-amd64.tar.gz`, - }, - } -} - -func installRustToolchainStep(path string) step { - return step{ - Name: "Install Rust Toolchain", - Environment: map[string]value{"WORKSPACE_DIR": {raw: path}}, - Commands: []string{ - `set -u`, - `export PATH=/Users/build/.cargo/bin:$PATH`, - `mkdir -p ~/build-$DRONE_BUILD_NUMBER-$DRONE_BUILD_CREATED-toolchains`, - `export RUST_VERSION=$(make -C $WORKSPACE_DIR/go/src/github.com/gravitational/teleport/build.assets print-rust-version)`, - `export CARGO_HOME=~/build-$DRONE_BUILD_NUMBER-$DRONE_BUILD_CREATED-toolchains`, - `export RUST_HOME=$CARGO_HOME`, - `rustup toolchain install $RUST_VERSION`, - }, - } -} - -func cleanUpToolchainsStep(path string) step { - return step{ - Name: "Clean up toolchains (post)", - Environment: map[string]value{"WORKSPACE_DIR": {raw: path}}, - When: &condition{ - Status: []string{"success", "failure"}, - }, - Commands: []string{ - `set -u`, - `export PATH=/Users/build/.cargo/bin:$PATH`, - `export CARGO_HOME=~/build-$DRONE_BUILD_NUMBER-$DRONE_BUILD_CREATED-toolchains`, - `export RUST_HOME=$CARGO_HOME`, - `export RUST_VERSION=$(make -C $WORKSPACE_DIR/go/src/github.com/gravitational/teleport/build.assets print-rust-version)`, - `cd $WORKSPACE_DIR/go/src/github.com/gravitational/teleport`, - // clean up the rust toolchain even though we're about to delete the directory - // this ensures we don't leave behind a broken link - `rustup override unset`, - `rustup toolchain uninstall $RUST_VERSION`, - `rm -rf ~/build-$DRONE_BUILD_NUMBER-$DRONE_BUILD_CREATED-toolchains`, - }, - } -} - -func cleanUpExecStorageStep(path string) step { - return step{ - Name: "Clean up exec runner storage (post)", - Environment: map[string]value{"WORKSPACE_DIR": {raw: path}}, - Commands: []string{ - `set -u`, - `chmod -R u+rw $WORKSPACE_DIR`, - `rm -rf $WORKSPACE_DIR/go $WORKSPACE_DIR/.ssh`, - }, - } -} - -func darwinTagCheckoutCommands() []string { - return append(pushCheckoutCommandsDarwin(), - `mkdir -p $WORKSPACE_DIR/go/artifacts`, - `echo "${DRONE_TAG##v}" > $WORKSPACE_DIR/go/.version.txt`, - `cat $WORKSPACE_DIR/go/.version.txt`, - ) -} - -func darwinTagBuildCommands() []string { - return []string{ - `set -u`, - `export RUST_VERSION=$(make -C $WORKSPACE_DIR/go/src/github.com/gravitational/teleport/build.assets print-rust-version)`, - `export CARGO_HOME=~/build-$DRONE_BUILD_NUMBER-$DRONE_BUILD_CREATED-toolchains`, - `export RUST_HOME=$CARGO_HOME`, - `export PATH=~/build-$DRONE_BUILD_NUMBER-$DRONE_BUILD_CREATED-toolchains/go/bin:$CARGO_HOME/bin:/Users/build/.cargo/bin:$PATH`, - `cd $WORKSPACE_DIR/go/src/github.com/gravitational/teleport`, - `rustup override set $RUST_VERSION`, - `make clean release OS=$OS ARCH=$ARCH`, - } -} - -func darwinTagCopyPackageArtifactCommands() []string { - return []string{ - `set -u`, - `cd $WORKSPACE_DIR/go/src/github.com/gravitational/teleport`, - // copy release archives to artifact directory - `cp teleport*.tar.gz $WORKSPACE_DIR/go/artifacts`, - `cp e/teleport-ent*.tar.gz $WORKSPACE_DIR/go/artifacts`, - // generate checksums (for mac) - `cd $WORKSPACE_DIR/go/artifacts && for FILE in teleport*.tar.gz; do shasum -a 256 $FILE > $FILE.sha256; done && ls -l`, - } -} - -func darwinUploadToS3Commands() []string { - return []string{ - `set -u`, - `cd $WORKSPACE_DIR/go/artifacts`, - `aws s3 sync . s3://$AWS_S3_BUCKET/teleport/tag/${DRONE_TAG##v}`, - } -} diff --git a/dronegen/mac_pkg.go b/dronegen/mac_pkg.go deleted file mode 100644 index 6603f12f19583..0000000000000 --- a/dronegen/mac_pkg.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "fmt" - "strings" -) - -func darwinPkgPipeline(name, makeTarget string, pkgGlobs []string) pipeline { - p := newDarwinPipeline(name) - p.Trigger = triggerTag - p.DependsOn = []string{"build-darwin-amd64"} - p.Steps = []step{ - setUpExecStorageStep(p.Workspace.Path), - { - Name: "Check out code", - Environment: map[string]value{ - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - "GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"}, - }, - Commands: darwinTagCheckoutCommands(), - }, - { - Name: "Download built tarball artifacts from S3", - Environment: map[string]value{ - "AWS_REGION": {raw: "us-west-2"}, - "AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"}, - "AWS_ACCESS_KEY_ID": {fromSecret: "AWS_ACCESS_KEY_ID"}, - "AWS_SECRET_ACCESS_KEY": {fromSecret: "AWS_SECRET_ACCESS_KEY"}, - "GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"}, - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - }, - Commands: darwinTagDownloadArtifactCommands(), - }, - { - Name: "Build Mac pkg release artifacts", - Environment: map[string]value{ - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - "APPLE_USERNAME": {fromSecret: "APPLE_USERNAME"}, - "APPLE_PASSWORD": {fromSecret: "APPLE_PASSWORD"}, - "BUILDBOX_PASSWORD": {fromSecret: "BUILDBOX_PASSWORD"}, - "OSS_TARBALL_PATH": {raw: "/tmp/build-darwin-amd64-pkg/go/artifacts"}, - "ENT_TARBALL_PATH": {raw: "/tmp/build-darwin-amd64-pkg/go/artifacts"}, - "OS": {raw: "darwin"}, - "ARCH": {raw: "amd64"}, - }, - Commands: darwinTagPackageCommands(makeTarget), - }, - { - Name: "Copy Mac pkg artifacts", - Environment: map[string]value{ - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - }, - Commands: darwinTagCopyPkgArtifactCommands(pkgGlobs), - }, - { - Name: "Upload to S3", - Environment: map[string]value{ - "AWS_REGION": {raw: "us-west-2"}, - "AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"}, - "AWS_ACCESS_KEY_ID": {fromSecret: "AWS_ACCESS_KEY_ID"}, - "AWS_SECRET_ACCESS_KEY": {fromSecret: "AWS_SECRET_ACCESS_KEY"}, - "WORKSPACE_DIR": {raw: p.Workspace.Path}, - }, - Commands: []string{ - `set -u`, - `cd $WORKSPACE_DIR/go/artifacts`, - `aws s3 sync . s3://$AWS_S3_BUCKET/teleport/tag/${DRONE_TAG##v}`, - }, - }, - cleanUpExecStorageStep(p.Workspace.Path), - } - - return p -} - -func darwinTeleportPkgPipeline() pipeline { - return darwinPkgPipeline("build-darwin-amd64-pkg", "pkg", []string{"build/teleport*.pkg", "e/build/teleport-ent*.pkg"}) -} - -func darwinTshPkgPipeline() pipeline { - return darwinPkgPipeline("build-darwin-amd64-pkg-tsh", "pkg-tsh", []string{"build/tsh*.pkg"}) -} - -func darwinTagDownloadArtifactCommands() []string { - return []string{ - `set -u`, - `export VERSION=$(cat $WORKSPACE_DIR/go/.version.txt)`, - `export S3_PATH="tag/$${DRONE_TAG##v}/"`, - `aws s3 cp s3://$AWS_S3_BUCKET/teleport/$${S3_PATH}teleport-v$${VERSION}-darwin-amd64-bin.tar.gz $WORKSPACE_DIR/go/artifacts/`, - `aws s3 cp s3://$AWS_S3_BUCKET/teleport/$${S3_PATH}teleport-ent-v$${VERSION}-darwin-amd64-bin.tar.gz $WORKSPACE_DIR/go/artifacts/`, - } -} - -func darwinTagPackageCommands(target string) []string { - return []string{ - `set -u`, - `cd $WORKSPACE_DIR/go/src/github.com/gravitational/teleport`, - `export VERSION=$(cat $WORKSPACE_DIR/go/.version.txt)`, - // set HOME explicitly (as Drone overrides it normally) - `export HOME=/Users/build`, - // unlock login keychain - `security unlock-keychain -p $${BUILDBOX_PASSWORD} login.keychain`, - // show available certificates - `security find-identity -v`, - // build pkg, target is `pkg` for teleport, `pkg-tsh` for tsh - fmt.Sprintf(`make %s OS=$OS ARCH=$ARCH`, target), - } -} - -func darwinTagCopyPkgArtifactCommands(pkgGlobs []string) []string { - return []string{ - `set -u`, - `cd $WORKSPACE_DIR/go/src/github.com/gravitational/teleport`, - // delete temporary tarball artifacts so we don't re-upload them in the next stage - `rm -rf $WORKSPACE_DIR/go/artifacts/*.tar.gz`, - // copy release archives to artifact directory - fmt.Sprintf(`cp %s $WORKSPACE_DIR/go/artifacts/`, strings.Join(pkgGlobs, " ")), - // generate checksums (for mac) - `cd $WORKSPACE_DIR/go/artifacts && for FILE in *.pkg; do shasum -a 256 $FILE > $FILE.sha256; done && ls -l`, - } -} diff --git a/dronegen/main.go b/dronegen/main.go deleted file mode 100644 index 509cf67e5b05b..0000000000000 --- a/dronegen/main.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - - "gopkg.in/yaml.v2" -) - -func main() { - if err := checkDroneCLI(); err != nil { - fmt.Println(err) - os.Exit(1) - } - var pipelines []pipeline - - pipelines = append(pipelines, testPipelines()...) - pipelines = append(pipelines, pushPipelines()...) - pipelines = append(pipelines, tagPipelines()...) - pipelines = append(pipelines, cronPipelines()...) - pipelines = append(pipelines, promoteBuildPipeline()) - pipelines = append(pipelines, updateDocsPipeline()) - pipelines = append(pipelines, buildboxPipeline()) - - if err := writePipelines(".drone.yml", pipelines); err != nil { - fmt.Println("failed writing drone pipelines:", err) - os.Exit(1) - } - - if err := signDroneConfig(); err != nil { - fmt.Println("failed signing .drone.yml:", err) - os.Exit(1) - } -} - -func writePipelines(path string, newPipelines []pipeline) error { - // Read the existing config and replace only those pipelines defined in - // newPipelines. - // - // TODO: When all pipelines are migrated, remove this merging logic and - // write the file directly. This will be simpler and allow cleanup of - // pipelines when they are removed from this generator. - existingConfig, err := ioutil.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read existing config: %w", err) - } - existingPipelines, err := parsePipelines(existingConfig) - if err != nil { - return fmt.Errorf("failed to parse existing config: %w", err) - } - - newPipelinesSet := make(map[string]pipeline, len(newPipelines)) - for _, p := range newPipelines { - // TODO: remove this check once promoteBuildPipeline and - // updateDocsPipeline are implemented. - if p.Name == "" { - continue - } - newPipelinesSet[p.Name] = p - } - - pipelines := existingPipelines - // Overwrite all existing pipelines with new ones that have the same name. - for i, p := range pipelines { - if np, ok := newPipelinesSet[p.Name]; ok { - out, err := yaml.Marshal(np) - if err != nil { - return fmt.Errorf("failed to encode pipelines: %w", err) - } - // Add a little note about this being generated. - out = append([]byte(np.comment), out...) - pipelines[i] = parsedPipeline{pipeline: np, raw: out} - delete(newPipelinesSet, np.Name) - } - } - // If we decide to add new pipelines before everything is migrated to this - // generator, this check needs to change. - if len(newPipelinesSet) != 0 { - var names []string - for n := range newPipelinesSet { - names = append(names, n) - } - return fmt.Errorf("pipelines %q don't exist in the current config, aborting", names) - } - - var pipelinesEnc [][]byte - for _, p := range pipelines { - pipelinesEnc = append(pipelinesEnc, p.raw) - } - configData := bytes.Join(pipelinesEnc, []byte("\n---\n")) - - return ioutil.WriteFile(path, configData, 0664) -} - -// parsedPipeline is a single pipeline parsed from .drone.yml along with its -// unparsed form. It's used to preserve YAML comments and minimize diffs due to -// formatting. -// -// TODO: remove this when all pipelines are migrated. All comments will be -// moved to this generator instead. -type parsedPipeline struct { - pipeline - raw []byte -} - -func parsePipelines(data []byte) ([]parsedPipeline, error) { - chunks := bytes.Split(data, []byte("\n---\n")) - var pipelines []parsedPipeline - for _, c := range chunks { - // Discard the signature, it will be re-generated. - if bytes.HasPrefix(c, []byte("kind: signature")) { - continue - } - var p pipeline - if err := yaml.UnmarshalStrict(c, &p); err != nil { - return nil, err - } - pipelines = append(pipelines, parsedPipeline{pipeline: p, raw: c}) - } - return pipelines, nil -} diff --git a/dronegen/misc.go b/dronegen/misc.go deleted file mode 100644 index e2d953c5d6ad9..0000000000000 --- a/dronegen/misc.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -func promoteBuildPipeline() pipeline { - // TODO: migrate - return pipeline{} -} - -func updateDocsPipeline() pipeline { - // TODO: migrate - return pipeline{} -} diff --git a/dronegen/push.go b/dronegen/push.go deleted file mode 100644 index 6b28c049767a9..0000000000000 --- a/dronegen/push.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import "fmt" - -// pushCheckoutCommands builds a list of commands for Drone to check out a git commit on a push build -func pushCheckoutCommands(fips bool) []string { - commands := []string{ - `mkdir -p /go/src/github.com/gravitational/teleport /go/cache`, - `cd /go/src/github.com/gravitational/teleport`, - `git init && git remote add origin ${DRONE_REMOTE_URL}`, - `git fetch origin`, - `git checkout -qf ${DRONE_COMMIT_SHA}`, - // this is allowed to fail because pre-4.3 Teleport versions don't use the webassets submodule - `git submodule update --init webassets || true`, - `mkdir -m 0700 /root/.ssh && echo "$GITHUB_PRIVATE_KEY" > /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa`, - `ssh-keyscan -H github.com > /root/.ssh/known_hosts 2>/dev/null && chmod 600 /root/.ssh/known_hosts`, - `git submodule update --init e`, - // do a recursive submodule checkout to get both webassets and webassets/e - // this is allowed to fail because pre-4.3 Teleport versions don't use the webassets submodule - `git submodule update --init --recursive webassets || true`, - `rm -f /root/.ssh/id_rsa`, - } - if fips { - commands = append(commands, `if [[ "${DRONE_TAG}" != "" ]]; then echo "${DRONE_TAG##v}" > /go/.version.txt; else egrep ^VERSION Makefile | cut -d= -f2 > /go/.version.txt; fi; cat /go/.version.txt`) - } - return commands -} - -// pushBuildCommands generates a list of commands for Drone to build an artifact as part of a push build -func pushBuildCommands(b buildType) []string { - commands := []string{ - `apk add --no-cache make`, - `chown -R $UID:$GID /go`, - `cd /go/src/github.com/gravitational/teleport`, - } - if b.fips { - commands = append(commands, - `export VERSION=$(cat /go/.version.txt)`, - ) - } - commands = append(commands, - fmt.Sprintf(`make -C build.assets %s`, releaseMakefileTarget(b)), - ) - return commands -} - -// pushPipelines builds all applicable push pipeline combinations -func pushPipelines() []pipeline { - var ps []pipeline - for _, arch := range []string{"amd64", "386", "arm", "arm64"} { - for _, fips := range []bool{false, true} { - if arch != "amd64" && fips { - // FIPS mode only supported on linux/amd64 - continue - } - ps = append(ps, pushPipeline(buildType{os: "linux", arch: arch, fips: fips})) - } - } - - // Only amd64 Windows is supported for now. - ps = append(ps, pushPipeline(buildType{os: "windows", arch: "amd64", windowsUnsigned: true})) - - ps = append(ps, darwinPushPipeline()) - return ps -} - -// pushPipeline generates a push pipeline for a given combination of os/arch/FIPS -func pushPipeline(b buildType) pipeline { - if b.os == "" { - panic("b.os must be set") - } - if b.arch == "" { - panic("b.arch must be set") - } - - pipelineName := fmt.Sprintf("push-build-%s-%s", b.os, b.arch) - pushEnvironment := map[string]value{ - "UID": {raw: "1000"}, - "GID": {raw: "1000"}, - "GOCACHE": {raw: "/go/cache"}, - "GOPATH": {raw: "/go"}, - "OS": {raw: b.os}, - "ARCH": {raw: b.arch}, - } - if b.fips { - pipelineName += "-fips" - pushEnvironment["FIPS"] = value{raw: "yes"} - } - - p := newKubePipeline(pipelineName) - p.Environment = map[string]value{ - "RUNTIME": goRuntime, - "UID": {raw: "1000"}, - "GID": {raw: "1000"}, - } - p.Trigger = triggerPush - p.Workspace = workspace{Path: "/go"} - p.Volumes = dockerVolumes() - p.Services = []service{ - dockerService(), - } - p.Steps = []step{ - { - Name: "Check out code", - Image: "docker:git", - Environment: map[string]value{ - "GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"}, - }, - Commands: pushCheckoutCommands(b.fips), - }, - waitForDockerStep(), - { - Name: "Build artifacts", - Image: "docker", - Environment: pushEnvironment, - Volumes: dockerVolumeRefs(), - Commands: pushBuildCommands(b), - }, - { - Name: "Send Slack notification", - Image: "plugins/slack", - Settings: map[string]value{ - "webhook": {fromSecret: "SLACK_WEBHOOK_DEV_TELEPORT"}, - }, - Template: []string{ - `*{{#success build.status}}✔{{ else }}✘{{/success}} {{ uppercasefirst build.status }}: Build #{{ build.number }}* (type: ` + "`{{ build.event }}`" + `) -` + "`${DRONE_STAGE_NAME}`" + ` artifact build failed. -*Warning:* This is a genuine failure to build the Teleport binary from ` + "`{{ build.branch }}`" + ` (likely due to a bad merge or commit) and should be investigated immediately. -Commit: -Branch: -Author: -<{{ build.link }}|Visit Drone build page ↗> -`, - }, - When: &condition{Status: []string{"failure"}}, - }, - } - return p -} diff --git a/dronegen/tag.go b/dronegen/tag.go deleted file mode 100644 index d27451adf7628..0000000000000 --- a/dronegen/tag.go +++ /dev/null @@ -1,424 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "fmt" -) - -const ( - // rpmPackage is the RPM package type - rpmPackage = "rpm" - // debPackage is the DEB package type - debPackage = "deb" -) - -// tagCheckoutCommands builds a list of commands for Drone to check out a git commit on a tag build -func tagCheckoutCommands(fips bool) []string { - commands := []string{ - `mkdir -p /go/src/github.com/gravitational/teleport`, - `cd /go/src/github.com/gravitational/teleport`, - `git clone https://github.com/gravitational/${DRONE_REPO_NAME}.git .`, - `git checkout ${DRONE_TAG:-$DRONE_COMMIT}`, - // fetch enterprise submodules - `mkdir -m 0700 /root/.ssh && echo -n "$GITHUB_PRIVATE_KEY" > /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa`, - `ssh-keyscan -H github.com > /root/.ssh/known_hosts 2>/dev/null && chmod 600 /root/.ssh/known_hosts`, - `git submodule update --init e`, - // this is allowed to fail because pre-4.3 Teleport versions don't use the webassets submodule - `git submodule update --init --recursive webassets || true`, - `rm -f /root/.ssh/id_rsa`, - // create necessary directories - `mkdir -p /go/cache /go/artifacts`, - // set version - `if [[ "${DRONE_TAG}" != "" ]]; then echo "${DRONE_TAG##v}" > /go/.version.txt; else egrep ^VERSION Makefile | cut -d= -f2 > /go/.version.txt; fi; cat /go/.version.txt`, - } - return commands -} - -// tagBuildCommands generates a list of commands for Drone to build an artifact as part of a tag build -func tagBuildCommands(b buildType) []string { - commands := []string{ - `apk add --no-cache make`, - `chown -R $UID:$GID /go`, - `cd /go/src/github.com/gravitational/teleport`, - } - - if b.fips { - commands = append(commands, - "export VERSION=$(cat /go/.version.txt)", - ) - } - - // For Windows builds, configure code signing. - if b.os == "windows" { - commands = append(commands, - `echo -n "$WINDOWS_SIGNING_CERT" | base64 -d > windows-signing-cert.pfx`, - ) - } - - commands = append(commands, - fmt.Sprintf( - `make -C build.assets %s`, releaseMakefileTarget(b), - ), - ) - - if b.os == "windows" { - commands = append(commands, - `rm -f windows-signing-cert.pfx`, - ) - } - - return commands -} - -// tagCopyArtifactCommands generates a set of commands to find and copy built tarball artifacts as part of a tag build -func tagCopyArtifactCommands(b buildType) []string { - extension := ".tar.gz" - if b.os == "windows" { - extension = ".zip" - } - - commands := []string{ - `cd /go/src/github.com/gravitational/teleport`, - } - - // don't copy OSS artifacts for any FIPS build - if !b.fips { - commands = append(commands, - fmt.Sprintf(`find . -maxdepth 1 -iname "teleport*%s" -print -exec cp {} /go/artifacts \;`, extension), - ) - } - - // copy enterprise artifacts - if b.os == "windows" { - commands = append(commands, - `export VERSION=$(cat /go/.version.txt)`, - `cp /go/artifacts/teleport-v$${VERSION}-windows-amd64-bin.zip /go/artifacts/teleport-ent-v$${VERSION}-windows-amd64-bin.zip`, - ) - } else { - commands = append(commands, - `find e/ -maxdepth 1 -iname "teleport*.tar.gz" -print -exec cp {} /go/artifacts \;`, - ) - } - - // we need to specifically rename artifacts which are created for CentOS - // these is the only special case where renaming is not handled inside the Makefile - if b.centos6 { - // for CentOS 6 we don't support FIPS, just OSS and enterprise - commands = append(commands, - `export VERSION=$(cat /go/.version.txt)`, - `mv /go/artifacts/teleport-v$${VERSION}-linux-amd64-bin.tar.gz /go/artifacts/teleport-v$${VERSION}-linux-amd64-centos6-bin.tar.gz`, - `mv /go/artifacts/teleport-ent-v$${VERSION}-linux-amd64-bin.tar.gz /go/artifacts/teleport-ent-v$${VERSION}-linux-amd64-centos6-bin.tar.gz`, - ) - } else if b.centos7 { - // for CentOS 7, we support OSS, Enterprise, and FIPS (Enterprise only) - commands = append(commands, `export VERSION=$(cat /go/.version.txt)`) - if !b.fips { - commands = append(commands, - `mv /go/artifacts/teleport-v$${VERSION}-linux-amd64-bin.tar.gz /go/artifacts/teleport-v$${VERSION}-linux-amd64-centos7-bin.tar.gz`, - `mv /go/artifacts/teleport-ent-v$${VERSION}-linux-amd64-bin.tar.gz /go/artifacts/teleport-ent-v$${VERSION}-linux-amd64-centos7-bin.tar.gz`, - ) - } else { - commands = append(commands, - `mv /go/artifacts/teleport-ent-v$${VERSION}-linux-amd64-fips-bin.tar.gz /go/artifacts/teleport-ent-v$${VERSION}-linux-amd64-centos7-fips-bin.tar.gz`, - ) - } - } - - // generate checksums - commands = append(commands, fmt.Sprintf(`cd /go/artifacts && for FILE in teleport*%s; do sha256sum $FILE > $FILE.sha256; done && ls -l`, extension)) - return commands -} - -type s3Settings struct { - region string - source string - target string - stripPrefix string -} - -// uploadToS3Step generates an S3 upload step -func uploadToS3Step(s s3Settings) step { - return step{ - Name: "Upload to S3", - Image: "plugins/s3", - Settings: map[string]value{ - "bucket": {fromSecret: "AWS_S3_BUCKET"}, - "access_key": {fromSecret: "AWS_ACCESS_KEY_ID"}, - "secret_key": {fromSecret: "AWS_SECRET_ACCESS_KEY"}, - "region": {raw: s.region}, - "source": {raw: s.source}, - "target": {raw: s.target}, - "strip_prefix": {raw: s.stripPrefix}, - }, - } -} - -// tagPipelines builds all applicable tag pipeline combinations -func tagPipelines() []pipeline { - var ps []pipeline - // regular tarball builds - for _, arch := range []string{"amd64", "386", "arm", "arm64"} { - for _, fips := range []bool{false, true} { - if arch != "amd64" && fips { - // FIPS mode only supported on linux/amd64 - continue - } - ps = append(ps, tagPipeline(buildType{os: "linux", arch: arch, fips: fips})) - - // RPM/DEB package builds - for _, packageType := range []string{rpmPackage, debPackage} { - ps = append(ps, tagPackagePipeline(packageType, buildType{os: "linux", arch: arch, fips: fips})) - } - } - } - - // Only amd64 Windows is supported for now. - ps = append(ps, tagPipeline(buildType{os: "windows", arch: "amd64"})) - - // Also add CentOS artifacts - // CentOS 6 FIPS builds have been removed in Teleport 7.0. See https://github.com/gravitational/teleport/issues/7207 - ps = append(ps, tagPipeline(buildType{os: "linux", arch: "amd64", centos6: true})) - ps = append(ps, tagPipeline(buildType{os: "linux", arch: "amd64", centos7: true})) - ps = append(ps, tagPipeline(buildType{os: "linux", arch: "amd64", centos7: true, fips: true})) - - ps = append(ps, darwinTagPipeline(), darwinTeleportPkgPipeline(), darwinTshPkgPipeline()) - return ps -} - -// tagPipeline generates a tag pipeline for a given combination of os/arch/FIPS -func tagPipeline(b buildType) pipeline { - if b.os == "" { - panic("b.os must be set") - } - if b.arch == "" { - panic("b.arch must be set") - } - - pipelineName := fmt.Sprintf("build-%s-%s", b.os, b.arch) - if b.centos6 { - pipelineName += "-centos6" - } else if b.centos7 { - pipelineName += "-centos7" - } - tagEnvironment := map[string]value{ - "UID": {raw: "1000"}, - "GID": {raw: "1000"}, - "GOCACHE": {raw: "/go/cache"}, - "GOPATH": {raw: "/go"}, - "OS": {raw: b.os}, - "ARCH": {raw: b.arch}, - } - if b.fips { - pipelineName += "-fips" - tagEnvironment["FIPS"] = value{raw: "yes"} - } - - if b.os == "windows" { - tagEnvironment["WINDOWS_SIGNING_CERT"] = value{fromSecret: "WINDOWS_SIGNING_CERT"} - } - - p := newKubePipeline(pipelineName) - p.Environment = map[string]value{ - "RUNTIME": goRuntime, - } - p.Trigger = triggerTag - p.Workspace = workspace{Path: "/go"} - p.Volumes = dockerVolumes() - p.Services = []service{ - dockerService(), - } - p.Steps = []step{ - { - Name: "Check out code", - Image: "docker:git", - Environment: map[string]value{ - "GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"}, - }, - Commands: tagCheckoutCommands(b.fips), - }, - waitForDockerStep(), - { - Name: "Build artifacts", - Image: "docker", - Environment: tagEnvironment, - Volumes: dockerVolumeRefs(), - Commands: tagBuildCommands(b), - }, - { - Name: "Copy artifacts", - Image: "docker", - Commands: tagCopyArtifactCommands(b), - }, - uploadToS3Step(s3Settings{ - region: "us-west-2", - source: "/go/artifacts/*", - target: "teleport/tag/${DRONE_TAG##v}", - stripPrefix: "/go/artifacts/", - }), - } - return p -} - -// tagDownloadArtifactCommands generates a set of commands to download appropriate artifacts for creating a package as part of a tag build -func tagDownloadArtifactCommands(b buildType) []string { - commands := []string{ - `export VERSION=$(cat /go/.version.txt)`, - `if [[ "${DRONE_TAG}" != "" ]]; then export S3_PATH="tag/$${DRONE_TAG##v}/"; else export S3_PATH="tag/"; fi`, - } - artifactOSS := true - artifactType := fmt.Sprintf("%s-%s", b.os, b.arch) - if b.fips { - artifactType += "-fips" - artifactOSS = false - } - - if artifactOSS { - commands = append(commands, - fmt.Sprintf(`aws s3 cp s3://$AWS_S3_BUCKET/teleport/$${S3_PATH}teleport-v$${VERSION}-%s-bin.tar.gz /go/artifacts/`, artifactType), - ) - } - commands = append(commands, - fmt.Sprintf(`aws s3 cp s3://$AWS_S3_BUCKET/teleport/$${S3_PATH}teleport-ent-v$${VERSION}-%s-bin.tar.gz /go/artifacts/`, artifactType), - ) - return commands -} - -// tagCopyPackageArtifactCommands generates a set of commands to find and copy built package artifacts as part of a tag build -func tagCopyPackageArtifactCommands(b buildType, packageType string) []string { - commands := []string{ - `cd /go/src/github.com/gravitational/teleport`, - } - if !b.fips { - commands = append(commands, fmt.Sprintf(`find build -maxdepth 1 -iname "teleport*.%s*" -print -exec cp {} /go/artifacts \;`, packageType)) - } - commands = append(commands, fmt.Sprintf(`find e/build -maxdepth 1 -iname "teleport*.%s*" -print -exec cp {} /go/artifacts \;`, packageType)) - return commands -} - -// tagPackagePipeline generates a tag package pipeline for a given combination of os/arch/FIPS -func tagPackagePipeline(packageType string, b buildType) pipeline { - if packageType == "" { - panic("packageType must be set") - } - if b.os == "" { - panic("b.os must be set") - } - if b.arch == "" { - panic("b.arch must be set") - } - - environment := map[string]value{ - "ARCH": {raw: b.arch}, - "TMPDIR": {raw: "/go"}, - "ENT_TARBALL_PATH": {raw: "/go/artifacts"}, - } - - dependentPipeline := fmt.Sprintf("build-%s-%s", b.os, b.arch) - packageBuildCommands := []string{ - `apk add --no-cache bash curl gzip make tar`, - `cd /go/src/github.com/gravitational/teleport`, - `export VERSION=$(cat /go/.version.txt)`, - } - - makeCommand := fmt.Sprintf("make %s", packageType) - if b.fips { - dependentPipeline += "-fips" - environment["FIPS"] = value{raw: "yes"} - environment["RUNTIME"] = value{raw: "fips"} - makeCommand = fmt.Sprintf("make -C e %s", packageType) - } else { - environment["OSS_TARBALL_PATH"] = value{raw: "/go/artifacts"} - } - - packageDockerVolumes := dockerVolumes() - packageDockerVolumeRefs := dockerVolumeRefs() - packageDockerService := dockerService() - - switch packageType { - case rpmPackage: - environment["GNUPG_DIR"] = value{raw: "/tmpfs/gnupg"} - environment["GPG_RPM_SIGNING_ARCHIVE"] = value{fromSecret: "GPG_RPM_SIGNING_ARCHIVE"} - packageBuildCommands = append(packageBuildCommands, - `mkdir -m0700 $GNUPG_DIR`, - `echo "$GPG_RPM_SIGNING_ARCHIVE" | base64 -d | tar -xzf - -C $GNUPG_DIR`, - `chown -R root:root $GNUPG_DIR`, - makeCommand, - `rm -rf $GNUPG_DIR`, - ) - // RPM builds require tmpfs to hold the key material in memory. - packageDockerVolumes = dockerVolumes(volumeTmpfs) - packageDockerVolumeRefs = dockerVolumeRefs(volumeRefTmpfs) - packageDockerService = dockerService(volumeRefTmpfs) - case debPackage: - packageBuildCommands = append(packageBuildCommands, - makeCommand, - ) - default: - panic("packageType is not set") - } - - pipelineName := fmt.Sprintf("%s-%s", dependentPipeline, packageType) - - p := newKubePipeline(pipelineName) - p.Trigger = triggerTag - p.DependsOn = []string{dependentPipeline} - p.Workspace = workspace{Path: "/go"} - p.Volumes = packageDockerVolumes - p.Services = []service{ - packageDockerService, - } - p.Steps = []step{ - { - Name: "Check out code", - Image: "docker:git", - Environment: map[string]value{ - "GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"}, - }, - Commands: tagCheckoutCommands(b.fips), - }, - waitForDockerStep(), - { - Name: "Download artifacts from S3", - Image: "amazon/aws-cli", - Environment: map[string]value{ - "AWS_REGION": {raw: "us-west-2"}, - "AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"}, - "AWS_ACCESS_KEY_ID": {fromSecret: "AWS_ACCESS_KEY_ID"}, - "AWS_SECRET_ACCESS_KEY": {fromSecret: "AWS_SECRET_ACCESS_KEY"}, - }, - Commands: tagDownloadArtifactCommands(b), - }, - { - Name: "Build artifacts", - Image: "docker", - Environment: environment, - Volumes: packageDockerVolumeRefs, - Commands: packageBuildCommands, - }, - { - Name: "Copy artifacts", - Image: "docker", - Commands: tagCopyPackageArtifactCommands(b, packageType), - }, - uploadToS3Step(s3Settings{ - region: "us-west-2", - source: "/go/artifacts/*", - target: "teleport/tag/${DRONE_TAG##v}", - stripPrefix: "/go/artifacts/", - }), - } - return p -} diff --git a/dronegen/tests.go b/dronegen/tests.go deleted file mode 100644 index b0ab6430adae0..0000000000000 --- a/dronegen/tests.go +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -func testPipelines() []pipeline { - return []pipeline{ - testCodePipeline(), - testDocsPipeline(), - } -} - -// testCheckoutCommands returns a set of commands for checking out Teleport's code -// Setting enterprise to true will also add a check against the Github API to determine whether -// the pull request comes from a code fork (and will only check out Enterprise code if it does not) -func testCheckoutCommands(enterprise bool) []string { - commands := []string{ - `mkdir -p /tmpfs/go/src/github.com/gravitational/teleport /tmpfs/go/cache`, - `cd /tmpfs/go/src/github.com/gravitational/teleport`, - `git init && git remote add origin ${DRONE_REMOTE_URL}`, - `# handle pull requests -if [ "${DRONE_BUILD_EVENT}" = "pull_request" ]; then - git fetch origin +refs/heads/${DRONE_COMMIT_BRANCH}: - git checkout ${DRONE_COMMIT_BRANCH} - git fetch origin ${DRONE_COMMIT_REF}: - git merge ${DRONE_COMMIT} -# handle tags -elif [ "${DRONE_BUILD_EVENT}" = "tag" ]; then - git fetch origin +refs/tags/${DRONE_TAG}: - git checkout -qf FETCH_HEAD -# handle pushes/other events -else - if [ "${DRONE_COMMIT_BRANCH}" = "" ]; then - git fetch origin - git checkout -qf ${DRONE_COMMIT_SHA} - else - git fetch origin +refs/heads/${DRONE_COMMIT_BRANCH}: - git checkout ${DRONE_COMMIT} -b ${DRONE_COMMIT_BRANCH} - fi -fi -`, - } - if enterprise { - commands = append(commands, - // this is allowed to fail because pre-4.3 Teleport versions - // don't use the webassets submodule. - `git submodule update --init webassets || true`, - // use the Github API to check whether this PR comes from a forked repo or not. - // if it does, don't check out the Enterprise code. - `if [ "${DRONE_BUILD_EVENT}" = "pull_request" ]; then - apk add --no-cache curl jq - export PR_REPO=$(curl -Ls https://api.github.com/repos/gravitational/${DRONE_REPO_NAME}/pulls/${DRONE_PULL_REQUEST} | jq -r '.head.repo.full_name') - echo "---> Source repo for PR ${DRONE_PULL_REQUEST}: $${PR_REPO}" - # if the source repo for the PR matches DRONE_REPO, then this is not a PR raised from a fork - if [ "$${PR_REPO}" = "${DRONE_REPO}" ] || [ "${DRONE_REPO}" = "gravitational/teleport-private" ]; then - mkdir -m 0700 /root/.ssh && echo -n "$GITHUB_PRIVATE_KEY" > /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa - ssh-keyscan -H github.com > /root/.ssh/known_hosts 2>/dev/null && chmod 600 /root/.ssh/known_hosts - git submodule update --init e - # do a recursive submodule checkout to get both webassets and webassets/e - # this is allowed to fail because pre-4.3 Teleport versions don't use the webassets submodule - git submodule update --init --recursive webassets || true - rm -f /root/.ssh/id_rsa - fi -fi -`, - ) - } - return commands -} - -// testCodePipeline returns a pipeline which runs the linter plus unit and integration tests -func testCodePipeline() pipeline { - p := newKubePipeline("test") - p.Environment = map[string]value{ - "RUNTIME": goRuntime, - "UID": {raw: "1000"}, - "GID": {raw: "1000"}, - } - p.Trigger = triggerPullRequest - p.Workspace = workspace{Path: "/go"} - p.Volumes = dockerVolumes( - volumeTmpfs, - volumeTmpIntegration, - volumeDockerTmpfs, - ) - p.Services = []service{ - dockerService( - volumeRefTmpfs, - volumeRefDockerTmpfs, - volumeRefTmpIntegration, - ), - } - goEnvironment := map[string]value{ - "GOCACHE": {raw: "/tmpfs/go/cache"}, - "GOPATH": {raw: "/tmpfs/go"}, - } - p.Steps = []step{ - { - Name: "Check out code", - Image: "docker:git", - Environment: map[string]value{ - "GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"}, - }, - Volumes: []volumeRef{ - volumeRefTmpfs, - }, - Commands: testCheckoutCommands(true), - }, - waitForDockerStep(), - { - Name: "Build buildbox", - Image: "docker", - Volumes: dockerVolumeRefs(volumeRefTmpfs), - Commands: []string{ - `apk add --no-cache make`, - `chown -R $UID:$GID /tmpfs/go`, - `docker pull quay.io/gravitational/teleport-buildbox:$RUNTIME || true`, - `cd /tmpfs/go/src/github.com/gravitational/teleport`, - `make -C build.assets buildbox`, - }, - }, - { - Name: "Run linter", - Image: "docker", - Environment: goEnvironment, - Volumes: dockerVolumeRefs(volumeRefTmpfs), - Commands: []string{ - `apk add --no-cache make`, - `chown -R $UID:$GID /tmpfs/go`, - `cd /tmpfs/go/src/github.com/gravitational/teleport`, - `make -C build.assets lint`, - }, - }, - { - // https://discourse.drone.io/t/how-to-exit-a-pipeline-early-without-failing/3951 - // this step looks at the output of git diff --raw to determine - // whether any files which don't match the pattern '^docs/', - // '.mdx$' or '.md$' were changed. if there are no changes to - // non-docs code, we skip the Teleport tests and exit early with a - // special Drone exit code to speed up iteration on docs (as milv - // is much quicker to run) - Name: "Optionally skip tests", - Image: "docker:git", - Volumes: []volumeRef{ - volumeRefTmpfs, - }, - Commands: []string{ - `cd /tmpfs/go/src/github.com/gravitational/teleport -echo -e "\n---> git diff --raw ${DRONE_COMMIT}..origin/${DRONE_COMMIT_BRANCH:-master}\n" -git diff --raw ${DRONE_COMMIT}..origin/${DRONE_COMMIT_BRANCH:-master} -git diff --raw ${DRONE_COMMIT}..origin/${DRONE_COMMIT_BRANCH:-master} | awk '{print $6}' | grep -Ev '^docs/' | grep -Ev '.mdx$' | grep -Ev '.md$' | grep -v ^$ | wc -l > /tmp/.change_count.txt -export CHANGE_COUNT=$(cat /tmp/.change_count.txt | tr -d '\n') -echo -e "\n---> Non-docs changes detected: $$CHANGE_COUNT" -if [ $$CHANGE_COUNT -gt 0 ]; then - echo "---> Teleport tests will run normally" -else - echo "---> Skipping Teleport tests and exiting early" - exit 78 -fi -echo "" -`, - }, - }, - { - Name: "Run unit and chaos tests", - Image: "docker", - Environment: goEnvironment, - Volumes: dockerVolumeRefs(volumeRefTmpfs), - Commands: []string{ - `apk add --no-cache make`, - `chown -R $UID:$GID /tmpfs/go`, - `cd /tmpfs/go/src/github.com/gravitational/teleport`, - `make -C build.assets test`, - }, - }, - { - // some integration tests can only be run as root, so we handle - // these separately using a build tag - Name: "Run root-only integration tests", - Image: "docker", - Environment: goEnvironment, - Volumes: dockerVolumeRefs(volumeRefTmpfs, volumeRefTmpIntegration), - Commands: []string{ - `apk add --no-cache make`, - `cd /tmpfs/go/src/github.com/gravitational/teleport`, - `make -C build.assets integration-root`, - }, - }, - { - Name: "Run integration tests", - Image: "docker", - Environment: map[string]value{ - "GOCACHE": {raw: "/tmpfs/go/cache"}, - "GOPATH": {raw: "/tmpfs/go"}, - "INTEGRATION_CI_KUBECONFIG": {fromSecret: "INTEGRATION_CI_KUBECONFIG"}, - "KUBECONFIG": {raw: "/tmpfs/go/kubeconfig.ci"}, - "TEST_KUBE": {raw: "true"}, - }, - Volumes: dockerVolumeRefs(volumeRefTmpfs, volumeRefTmpIntegration), - Commands: []string{ - `apk add --no-cache make`, - // write kubeconfig to disk for use in kube integration tests - `echo "$INTEGRATION_CI_KUBECONFIG" > "$KUBECONFIG"`, - `chown -R $UID:$GID /tmpfs/go`, - `cd /tmpfs/go/src/github.com/gravitational/teleport`, - `make -C build.assets integration`, - `rm -f "$KUBECONFIG"`, - }, - }, - } - return p -} - -func testDocsPipeline() pipeline { - p := newKubePipeline("test-docs") - p.Trigger = triggerPullRequest - p.Workspace = workspace{Path: "/go"} - p.Volumes = dockerVolumes( - volumeTmpfs, - volumeDockerTmpfs, - ) - p.Services = []service{ - dockerService( - volumeRefTmpfs, - volumeRefDockerTmpfs, - ), - } - p.Steps = []step{ - { - Name: "Check out code", - Image: "docker:git", - Volumes: []volumeRef{ - volumeRefTmpfs, - }, - Commands: testCheckoutCommands(false), - }, - waitForDockerStep(), - { - Name: "Run docs tests", - Image: "docker:git", - Environment: map[string]value{ - "GOCACHE": {raw: "/tmpfs/go/cache"}, - "UID": {raw: "1000"}, - "GID": {raw: "1000"}, - }, - Volumes: dockerVolumeRefs(volumeRefTmpfs), - Commands: []string{ - `apk add --no-cache make`, - `cd /tmpfs/go/src/github.com/gravitational/teleport`, - `chown -R $UID:$GID /tmpfs/go`, - `git diff --raw ${DRONE_COMMIT}..origin/${DRONE_COMMIT_BRANCH:-master} | awk '{print $6}' | grep -E '^docs' | { grep -v ^$ || true; } > /tmp/docs-changes.txt`, - `if [ $(cat /tmp/docs-changes.txt | wc -l) -gt 0 ]; then - echo "---> Changes to docs detected" - cat /tmp/docs-changes.txt - echo "---> Checking for trailing whitespace" - make docs-test-whitespace - echo "---> Checking for dead links" - make -C build.assets test-docs -else - echo "---> No changes to docs detected, not running tests" -fi -`, - }, - }, - } - return p -} diff --git a/dronegen/types.go b/dronegen/types.go deleted file mode 100644 index 65d2816632f5a..0000000000000 --- a/dronegen/types.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2021 Gravitational, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "errors" - "fmt" - "runtime" - "strings" -) - -// Types to mirror the YAML fields of the drone config. -// See https://docs.drone.io/pipeline/kubernetes/syntax/ and https://docs.drone.io/pipeline/exec/syntax/. - -type pipeline struct { - comment string - - Kind string `yaml:"kind"` - Type string `yaml:"type"` - Name string `yaml:"name"` - Environment map[string]value `yaml:"environment,omitempty"` - Trigger trigger `yaml:"trigger"` - Workspace workspace `yaml:"workspace,omitempty"` - Platform platform `yaml:"platform,omitempty"` - Clone clone `yaml:"clone,omitempty"` - DependsOn []string `yaml:"depends_on,omitempty"` - Concurrency concurrency `yaml:"concurrency,omitempty"` - Steps []step `yaml:"steps"` - Services []service `yaml:"services,omitempty"` - Volumes []volume `yaml:"volumes,omitempty"` -} - -func newKubePipeline(name string) pipeline { - return pipeline{ - comment: generatedComment(), - Kind: "pipeline", - Type: "kubernetes", - Name: name, - Clone: clone{Disable: true}, - } -} - -//nolint:deadcode,unused -func newExecPipeline(name string) pipeline { - return pipeline{ - comment: generatedComment(), - Kind: "pipeline", - Type: "exec", - Name: name, - Clone: clone{Disable: true}, - } -} - -func generatedComment() string { - c := `################################################ -# Generated using dronegen, do not edit by hand! -# Use 'make dronegen' to update. -` - _, file, line, ok := runtime.Caller(2) - if ok { - // Trim off the local path to the repo. - i := strings.LastIndex(file, "dronegen") - if i > 0 { - file = file[i:] - } - c += fmt.Sprintf("# Generated at %s:%d\n", file, line) - } - c += "################################################\n\n" - return c -} - -type trigger struct { - Event triggerRef `yaml:"event,omitempty"` - Cron triggerRef `yaml:"cron,omitempty"` - Target triggerRef `yaml:"target,omitempty"` - Ref triggerRef `yaml:"ref,omitempty"` - Repo triggerRef `yaml:"repo"` - Branch triggerRef `yaml:"branch,omitempty"` -} - -type triggerRef struct { - Include []string `yaml:"include,omitempty"` - Exclude []string `yaml:"exclude,omitempty"` -} - -// UnmarshalYAML parses trigger references as either a list of strings, or as -// include/exclude lists. Both are allowed by drone. -func (v *triggerRef) UnmarshalYAML(unmarshal func(interface{}) error) error { - var rawItems []string - if err := unmarshal(&rawItems); err == nil { - v.Include = rawItems - return nil - } - var regular struct { - Include []string `yaml:"include,omitempty"` - Exclude []string `yaml:"exclude,omitempty"` - } - if err := unmarshal(®ular); err == nil { - v.Include = regular.Include - v.Exclude = regular.Exclude - return nil - } - return errors.New("can't unmarshal the value as either string or from_secret reference") -} - -type workspace struct { - Path string `yaml:"path"` -} - -type clone struct { - Disable bool `yaml:"disable"` -} - -type platform struct { - OS string `yaml:"os"` - Arch string `yaml:"arch"` -} - -type concurrency struct { - Limit int `yaml:"limit"` -} - -type volume struct { - Name string `yaml:"name"` - Temp *volumeTemp `yaml:"temp,omitempty"` - Claim *volumeClaim `yaml:"claim,omitempty"` -} - -type volumeTemp struct { - Medium string `yaml:"medium,omitempty"` -} - -type volumeClaim struct { - Name string `yaml:"name"` -} - -type service struct { - Name string `yaml:"name"` - Image string `yaml:"image"` - Privileged bool `yaml:"privileged"` - Volumes []volumeRef `yaml:"volumes"` -} - -type volumeRef struct { - Name string `yaml:"name"` - Path string `yaml:"path"` -} - -type step struct { - Name string `yaml:"name"` - Image string `yaml:"image,omitempty"` - Commands []string `yaml:"commands,omitempty"` - Environment map[string]value `yaml:"environment,omitempty"` - Volumes []volumeRef `yaml:"volumes,omitempty"` - Settings map[string]value `yaml:"settings,omitempty"` - Template []string `yaml:"template,omitempty"` - When *condition `yaml:"when,omitempty"` - Failure string `yaml:"failure,omitempty"` -} - -type condition struct { - Status []string `yaml:"status,omitempty"` -} - -// value is a string value for key:value pairs like "environment" or -// "settings". Values can be either inline strings (raw) or references to -// secrets stored in Drone (fromSecret). -type value struct { - raw string - fromSecret string -} - -type valueFromSecret struct { - FromSecret string `yaml:"from_secret"` -} - -func (v value) MarshalYAML() (interface{}, error) { - if v.raw != "" && v.fromSecret != "" { - return nil, fmt.Errorf("value %+v has both raw and fromSecret set, can only have one", v) - } - if v.raw != "" { - return v.raw, nil - } - if v.fromSecret != "" { - return valueFromSecret{FromSecret: v.fromSecret}, nil - } - return nil, fmt.Errorf("value has neither raw nor fromSecret set, need one") -} - -func (v *value) UnmarshalYAML(unmarshal func(interface{}) error) error { - if err := unmarshal(&v.raw); err == nil { - return nil - } - var fs valueFromSecret - if err := unmarshal(&fs); err == nil { - v.fromSecret = fs.FromSecret - return nil - } - return errors.New("can't unmarshal the value as either string or from_secret reference") -}