2019-08-11 00:29:25 +03:00
// This file contains the logic for building our CI for Drone. The idea here is
// that we create a pipeline for all of the major tasks we need to perform
// (e.g. builds, E2E testing, conformance testing, releases). Each pipeline
// after the default builds on a previous pipeline.
2019-09-07 06:37:37 +03:00
// Generate with `drone jsonnet --source ./hack/drone.jsonnet --stream --format`
2019-08-11 00:29:25 +03:00
2019-08-03 00:08:24 +03:00
local build_container = 'autonomy/build-container:latest';
2019-08-11 00:29:25 +03:00
2019-12-23 21:36:14 +03:00
local secret = {
kind: 'secret',
name: 'kubeconfig',
get: {
path: 'buildx',
name: 'kubeconfig'
},
};
2019-08-11 00:29:25 +03:00
local volumes = {
dockersock: {
pipeline: {
2019-08-03 00:08:24 +03:00
name: 'dockersock',
2019-08-11 00:29:25 +03:00
temp: {},
},
step: {
name: $.dockersock.pipeline.name,
2019-08-03 00:08:24 +03:00
path: '/var/run',
2019-08-11 00:29:25 +03:00
},
2019-08-09 06:45:13 +03:00
},
2019-08-11 00:29:25 +03:00
2019-12-23 21:36:14 +03:00
docker: {
pipeline: {
name: 'docker',
temp: {},
},
step: {
name: $.docker.pipeline.name,
path: '/root/.docker/buildx',
},
},
kube: {
pipeline: {
name: 'kube',
temp: {},
},
step: {
name: $.kube.pipeline.name,
path: '/root/.kube',
},
},
2019-08-11 00:29:25 +03:00
dev: {
pipeline: {
2019-08-03 00:08:24 +03:00
name: 'dev',
2019-08-11 00:29:25 +03:00
host: {
2019-08-03 00:08:24 +03:00
path: '/dev',
2019-08-11 00:29:25 +03:00
},
},
step: {
name: $.dev.pipeline.name,
2019-08-03 00:08:24 +03:00
path: '/dev',
2019-08-11 00:29:25 +03:00
},
2019-08-09 06:45:13 +03:00
},
2019-08-11 00:29:25 +03:00
tmp: {
pipeline: {
2019-08-03 00:08:24 +03:00
name: 'tmp',
2019-08-11 00:29:25 +03:00
temp: {},
},
step: {
name: $.tmp.pipeline.name,
2019-08-03 00:08:24 +03:00
path: '/tmp',
2019-08-11 00:29:25 +03:00
},
2019-08-09 06:45:13 +03:00
},
2019-08-11 00:29:25 +03:00
ForStep(): [
self.dockersock.step,
2019-12-23 21:36:14 +03:00
self.docker.step,
self.kube.step,
2019-08-11 00:29:25 +03:00
self.dev.step,
self.tmp.step,
],
ForPipeline(): [
self.dockersock.pipeline,
2019-12-23 21:36:14 +03:00
self.docker.pipeline,
self.kube.pipeline,
2019-08-11 00:29:25 +03:00
self.dev.pipeline,
self.tmp.pipeline,
],
};
2019-08-09 06:45:13 +03:00
2019-08-11 00:29:25 +03:00
// This provides the docker service.
2019-08-09 06:45:13 +03:00
local docker = {
2019-08-03 00:08:24 +03:00
name: 'docker',
image: 'docker:19.03-dind',
entrypoint: ['dockerd'],
2019-08-09 06:45:13 +03:00
privileged: true,
command: [
2019-08-03 00:08:24 +03:00
'--dns=8.8.8.8',
'--dns=8.8.4.4',
'--mtu=1440',
'--log-level=error',
2019-08-09 06:45:13 +03:00
],
2019-12-27 21:12:04 +03:00
ports: [
6443,
50000,
],
2019-08-11 00:29:25 +03:00
volumes: volumes.ForStep(),
2019-08-09 06:45:13 +03:00
};
2019-12-24 20:28:58 +03:00
// Sets up the CI environment
local setup_ci = {
name: 'setup-ci',
2019-12-23 21:36:14 +03:00
image: 'autonomy/build-container:latest',
2019-08-09 06:45:13 +03:00
privileged: true,
2019-12-23 21:36:14 +03:00
environment: {
BUILDX_KUBECONFIG: { from_secret: secret.name },
2019-08-09 06:45:13 +03:00
},
2019-12-23 21:36:14 +03:00
commands: [
2019-12-24 20:28:58 +03:00
'git fetch --tags',
'apk add coreutils',
2019-12-23 21:36:14 +03:00
'echo -e "$BUILDX_KUBECONFIG" > /root/.kube/config',
'docker buildx create --driver kubernetes --driver-opt replicas=2 --driver-opt namespace=ci --driver-opt image=moby/buildkit:v0.6.2 --name ci --buildkitd-flags="--allow-insecure-entitlement security.insecure" --use',
'docker buildx inspect --bootstrap'
],
volumes: volumes.ForStep(),
2019-08-09 06:45:13 +03:00
};
2019-08-11 00:29:25 +03:00
// Step standardizes the creation of build steps. The name of the step is used
// as the target when building the make command. For example, if name equals
// "test", the resulting step command will be "make test". This is done to
// encourage alignment between this file and the Makefile, and gives us a
// standardized structure that should make things easier to reason about if we
// know that each step is essentially a Makefile target.
2019-12-04 18:22:36 +03:00
local Step(name, image='', target='', depends_on=[], environment={}) = {
2019-08-03 00:08:24 +03:00
local make = if target == '' then std.format('make %s', name) else std.format('make %s', target),
2019-12-04 18:22:36 +03:00
2019-08-11 00:29:25 +03:00
local common_env_vars = {
2019-08-03 00:08:24 +03:00
BINDIR: '/usr/local/bin',
2019-08-11 00:29:25 +03:00
},
2019-08-09 06:45:13 +03:00
2019-08-11 00:29:25 +03:00
name: name,
2019-12-04 18:22:36 +03:00
image: if image == '' then build_container else image,
2019-09-24 07:45:21 +03:00
pull: "always",
2019-08-11 00:29:25 +03:00
commands: [make],
environment: common_env_vars + environment,
volumes: volumes.ForStep(),
2019-08-09 06:45:13 +03:00
depends_on: [x.name for x in depends_on],
};
2019-08-11 00:29:25 +03:00
// Pipeline is a way to standardize the creation of pipelines. It supports
// using and existing pipeline as a base.
2019-12-23 21:36:14 +03:00
local Pipeline(name, steps=[], depends_on=[], with_docker=true, disable_clone=false) = {
2019-08-03 00:08:24 +03:00
local node = { 'node-role.kubernetes.io/ci': '' },
2019-08-09 06:45:13 +03:00
2019-08-03 00:08:24 +03:00
kind: 'pipeline',
2019-08-09 06:45:13 +03:00
name: name,
2019-08-11 00:29:25 +03:00
node: node,
services: [
if with_docker then docker,
],
2019-12-10 20:44:07 +03:00
[ if disable_clone then 'clone']: {
disable: true,
},
2019-09-24 07:45:21 +03:00
steps: steps,
2019-08-11 00:29:25 +03:00
volumes: volumes.ForPipeline(),
depends_on: [x.name for x in depends_on],
2019-08-09 06:45:13 +03:00
};
2019-08-11 00:29:25 +03:00
// Default pipeline.
2019-12-24 20:28:58 +03:00
local machined = Step("machined", depends_on=[setup_ci]);
2019-12-24 23:23:52 +03:00
local osd = Step("osd", depends_on=[setup_ci]);
local trustd = Step("trustd", depends_on=[setup_ci]);
local ntpd = Step("ntpd", depends_on=[setup_ci]);
local networkd = Step("networkd", depends_on=[setup_ci]);
local apid = Step("apid", depends_on=[setup_ci]);
2019-12-24 20:28:58 +03:00
local osctl_linux = Step("osctl-linux", depends_on=[setup_ci]);
local osctl_darwin = Step("osctl-darwin", depends_on=[setup_ci]);
2019-12-24 23:23:52 +03:00
local docs = Step("docs", depends_on=[osctl_linux]);
2019-12-24 20:28:58 +03:00
local integration_test = Step("integration-test", depends_on=[setup_ci]);
2019-12-24 23:23:52 +03:00
local rootfs = Step("rootfs", target="target-rootfs", depends_on=[machined, osd, trustd, ntpd, networkd, apid]);
2019-08-11 00:29:25 +03:00
local initramfs = Step("initramfs", depends_on=[rootfs]);
local installer = Step("installer", depends_on=[rootfs]);
2019-12-24 23:23:52 +03:00
local talos = Step("talos", depends_on=[rootfs]);
2019-12-24 20:28:58 +03:00
local golint = Step("lint-go", depends_on=[setup_ci]);
local protobuflint = Step("lint-protobuf", depends_on=[setup_ci]);
local markdownlint = Step("lint-markdown", depends_on=[setup_ci]);
2019-11-01 07:55:58 +03:00
local image_aws = Step("image-aws", depends_on=[installer]);
local image_azure = Step("image-azure", depends_on=[installer]);
local image_digital_ocean = Step("image-digital-ocean", depends_on=[installer]);
local image_gcp = Step("image-gcp", depends_on=[installer]);
local image_vmware = Step("image-vmware", depends_on=[installer]);
2019-12-24 23:23:52 +03:00
local unit_tests = Step("unit-tests", depends_on=[rootfs, talos]);
2019-12-24 20:28:58 +03:00
local unit_tests_race = Step("unit-tests-race", depends_on=[golint]);
2019-12-27 21:12:04 +03:00
local basic_integration = Step("basic-integration", depends_on=[unit_tests, talos, osctl_linux, integration_test]);
2019-08-09 06:45:13 +03:00
local coverage = {
2019-08-03 00:08:24 +03:00
name: 'coverage',
image: 'plugins/codecov',
settings: {
token: { from_secret: 'codecov_token' },
files: ['coverage.txt'],
2019-08-09 06:45:13 +03:00
},
2019-08-11 00:29:25 +03:00
when: {
2019-08-03 00:08:24 +03:00
event: ['pull_request'],
2019-08-09 06:45:13 +03:00
},
depends_on: [unit_tests.name],
};
2019-11-27 18:39:53 +03:00
local push_latest = {
name: 'push-latest',
2019-08-03 00:08:24 +03:00
image: 'autonomy/build-container:latest',
pull: 'always',
environment: {
DOCKER_USERNAME: { from_secret: 'docker_username' },
DOCKER_PASSWORD: { from_secret: 'docker_password' },
2019-08-09 06:45:13 +03:00
},
2019-12-26 17:53:24 +03:00
commands: ['make login', 'make push-latest'],
2019-08-11 00:29:25 +03:00
volumes: volumes.ForStep(),
2019-08-09 06:45:13 +03:00
when: {
2019-08-12 21:28:42 +03:00
event: {
2019-08-13 03:40:00 +03:00
exclude: [
2019-08-03 00:08:24 +03:00
'pull_request',
'promote',
2019-12-27 18:32:31 +03:00
'tag',
2019-12-28 03:55:29 +03:00
'cron',
2019-08-13 03:40:00 +03:00
],
2019-08-12 21:28:42 +03:00
},
2019-08-09 06:45:13 +03:00
},
2019-08-10 09:18:15 +03:00
depends_on: [basic_integration.name],
2019-08-09 06:45:13 +03:00
};
2019-08-11 00:29:25 +03:00
local default_steps = [
2019-12-24 20:28:58 +03:00
setup_ci,
2019-08-11 00:29:25 +03:00
machined,
osd,
2019-10-24 05:31:18 +03:00
apid,
2019-08-11 00:29:25 +03:00
trustd,
ntpd,
2019-08-03 00:08:24 +03:00
networkd,
2019-08-11 00:29:25 +03:00
osctl_linux,
osctl_darwin,
2019-12-24 23:23:52 +03:00
docs,
2019-11-06 15:46:19 +03:00
integration_test,
2019-08-09 06:45:13 +03:00
rootfs,
initramfs,
2019-08-11 00:29:25 +03:00
installer,
2019-12-24 23:23:52 +03:00
talos,
2019-12-24 20:28:58 +03:00
golint,
protobuflint,
2019-08-17 11:51:40 +03:00
markdownlint,
2019-11-01 07:55:58 +03:00
image_aws,
image_azure,
image_digital_ocean,
image_gcp,
image_vmware,
2019-08-09 06:45:13 +03:00
unit_tests,
2019-09-02 21:55:42 +03:00
unit_tests_race,
2019-08-09 06:45:13 +03:00
coverage,
basic_integration,
2019-11-27 18:39:53 +03:00
push_latest,
2019-08-09 06:45:13 +03:00
];
local default_trigger = {
trigger: {
cron: {
2019-08-03 00:08:24 +03:00
exclude: ['nightly'],
2019-08-09 06:45:13 +03:00
},
2019-08-12 21:28:42 +03:00
event: {
2019-08-13 03:40:00 +03:00
exclude: [
2019-08-03 00:08:24 +03:00
'tag',
'promote',
],
2019-08-09 06:45:13 +03:00
},
},
};
2019-08-03 00:08:24 +03:00
local default_pipeline = Pipeline('default', default_steps) + default_trigger;
2019-08-11 00:29:25 +03:00
// E2E pipeline.
local creds_env_vars = {
AZURE_SVC_ACCT: {from_secret: "azure_svc_acct"},
2019-08-12 00:38:24 +03:00
// TODO(andrewrynhard): Rename this to the GCP convention.
2019-08-11 00:29:25 +03:00
GCE_SVC_ACCT: {from_secret: "gce_svc_acct"},
PACKET_AUTH_TOKEN: {from_secret: "packet_auth_token"},
2019-09-07 06:37:37 +03:00
AWS_SVC_ACCT: {from_secret: "aws_svc_acct"},
2019-08-09 06:45:13 +03:00
};
2019-08-11 00:29:25 +03:00
local capi = Step("capi", depends_on=[basic_integration], environment=creds_env_vars);
2019-09-10 01:21:58 +03:00
local push_image_aws = Step("push-image-aws", depends_on=[image_aws], environment=creds_env_vars);
2019-08-11 00:29:25 +03:00
local push_image_azure = Step("push-image-azure", depends_on=[image_azure], environment=creds_env_vars);
2019-08-12 00:38:24 +03:00
local push_image_gcp = Step("push-image-gcp", depends_on=[image_gcp], environment=creds_env_vars);
2019-12-04 18:22:36 +03:00
local e2e_integration_aws = Step("e2e-integration-aws", target="e2e-integration", depends_on=[capi, push_image_aws], environment={PLATFORM: "aws"});
local e2e_integration_azure = Step("e2e-integration-azure", target="e2e-integration", depends_on=[capi, push_image_azure], environment={PLATFORM: "azure"});
local e2e_integration_gcp = Step("e2e-integration-gcp", target="e2e-integration", depends_on=[capi, push_image_gcp], environment={PLATFORM: "gcp"});
2019-08-11 00:29:25 +03:00
local e2e_steps = default_steps + [
capi,
2019-09-10 01:21:58 +03:00
push_image_aws,
2019-08-12 00:38:24 +03:00
push_image_gcp,
2019-11-07 18:56:11 +03:00
e2e_integration_aws,
2019-08-12 00:38:24 +03:00
e2e_integration_gcp,
2019-08-11 00:29:25 +03:00
];
2019-08-09 06:45:13 +03:00
local e2e_trigger = {
trigger: {
target: {
2019-08-03 00:08:24 +03:00
include: ['e2e'],
2019-08-09 06:45:13 +03:00
},
},
};
2019-08-03 00:08:24 +03:00
local e2e_pipeline = Pipeline('e2e', e2e_steps) + e2e_trigger;
2019-08-11 00:29:25 +03:00
// Conformance pipeline.
2019-12-04 18:22:36 +03:00
local conformance_aws = Step("conformance-aws", target="e2e-integration", depends_on=[capi, push_image_aws], environment={PLATFORM: "aws", CONFORMANCE: "run"});
local conformance_azure = Step("conformance-azure", target="e2e-integration", depends_on=[capi, push_image_azure], environment={PLATFORM: "azure", CONFORMANCE: "run"});
local conformance_gcp = Step("conformance-gcp", target="e2e-integration", depends_on=[capi, push_image_gcp], environment={PLATFORM: "gcp", CONFORMANCE: "run"});
2019-08-11 00:29:25 +03:00
2019-11-27 18:39:53 +03:00
local push_edge = {
name: 'push-edge',
image: 'autonomy/build-container:latest',
pull: 'always',
environment: {
DOCKER_USERNAME: { from_secret: 'docker_username' },
DOCKER_PASSWORD: { from_secret: 'docker_password' },
},
2019-12-26 17:53:24 +03:00
commands: ['make login', 'make push-edge'],
2019-11-27 18:39:53 +03:00
volumes: volumes.ForStep(),
when: {
event: {
exclude: [
'pull_request',
'promote',
2019-12-27 18:32:31 +03:00
'tag',
2019-11-27 18:39:53 +03:00
],
},
},
2019-12-27 18:32:31 +03:00
depends_on: [conformance_aws.name, conformance_gcp.name],
2019-11-27 18:39:53 +03:00
};
2019-08-11 00:29:25 +03:00
local conformance_steps = default_steps + [
2019-08-11 20:52:20 +03:00
capi,
2019-09-10 01:21:58 +03:00
push_image_aws,
2019-08-12 00:38:24 +03:00
push_image_gcp,
2019-09-10 01:21:58 +03:00
conformance_aws,
2019-08-12 00:38:24 +03:00
conformance_gcp,
2019-11-27 18:39:53 +03:00
push_edge,
2019-08-11 00:29:25 +03:00
];
2019-08-09 06:45:13 +03:00
local conformance_trigger = {
trigger: {
target: {
2019-08-03 00:08:24 +03:00
include: ['conformance'],
2019-08-09 06:45:13 +03:00
},
},
};
2019-08-03 00:08:24 +03:00
local conformance_pipeline = Pipeline('conformance', conformance_steps) + conformance_trigger;
2019-08-11 00:29:25 +03:00
// Nightly pipeline.
local nightly_trigger = {
trigger: {
cron: {
2019-08-03 00:08:24 +03:00
include: ['nightly'],
2019-08-11 00:29:25 +03:00
},
},
};
2019-08-03 00:08:24 +03:00
local nightly_pipeline = Pipeline('nightly', conformance_steps) + nightly_trigger;
2019-08-11 00:29:25 +03:00
// Release pipeline.
2019-08-11 19:54:33 +03:00
local aws_env_vars = {
2019-08-03 00:08:24 +03:00
AWS_ACCESS_KEY_ID: { from_secret: 'aws_access_key_id' },
AWS_SECRET_ACCESS_KEY: { from_secret: 'aws_secret_access_key' },
AWS_DEFAULT_REGION: 'us-west-2',
AWS_PUBLISH_REGIONS: 'us-west-2,us-east-1,us-east-2,us-west-1,eu-central-1',
2019-08-11 19:54:33 +03:00
};
local ami_trigger = {
when: {
2019-08-03 00:08:24 +03:00
event: ['tag'],
},
2019-08-11 19:54:33 +03:00
};
2019-08-03 00:08:24 +03:00
local kernel = Step('kernel');
local iso = Step('iso', depends_on=[installer]);
2019-08-11 19:54:33 +03:00
2019-08-11 00:29:25 +03:00
// TODO(andrewrynhard): We should run E2E tests on a release.
2019-08-03 00:08:24 +03:00
local release = {
name: 'release',
image: 'plugins/github-release',
settings: {
api_key: { from_secret: 'github_token' },
2019-08-11 00:29:25 +03:00
draft: true,
2019-12-24 23:23:52 +03:00
files: ['_out/*'],
2019-08-03 00:08:24 +03:00
checksum: ['sha256', 'sha512'],
2019-08-11 00:29:25 +03:00
},
when: {
2019-08-03 00:08:24 +03:00
event: ['tag'],
2019-08-11 00:29:25 +03:00
},
2019-11-27 18:39:53 +03:00
depends_on: [kernel.name, iso.name, image_gcp.name, image_azure.name, image_aws.name, push_latest.name]
2019-08-11 00:29:25 +03:00
};
local release_steps = default_steps + [
2019-08-11 20:29:45 +03:00
kernel,
iso,
2019-08-11 19:54:33 +03:00
release,
2019-08-11 00:29:25 +03:00
];
2019-08-09 06:45:13 +03:00
local release_trigger = {
trigger: {
2019-08-11 20:52:20 +03:00
event: [
2019-08-03 00:08:24 +03:00
'tag',
2019-08-11 20:52:20 +03:00
],
2019-08-09 06:45:13 +03:00
},
};
2019-08-03 00:08:24 +03:00
local release_pipeline = Pipeline('release', release_steps) + release_trigger;
2019-08-11 00:29:25 +03:00
// Notify pipeline.
local notify = {
2019-08-03 00:08:24 +03:00
name: 'slack',
image: 'plugins/slack',
2019-08-11 00:29:25 +03:00
settings:
{
2019-08-03 00:08:24 +03:00
webhook: { from_secret: 'slack_webhook' },
2019-09-09 18:51:10 +03:00
channel: 'proj-talos-maintainers',
2019-10-22 16:07:31 +03:00
link_names: true,
template: '{{#if build.pull }}
*{{#success build.status}}✓ Success{{else}}✕ Fail{{/success}}*: {{ repo.owner }}/{{ repo.name }} - <https://github.com/{{ repo.owner }}/{{ repo.name }}/pull/{{ build.pull }}|Pull Request #{{ build.pull }}>
{{else}}
*{{#success build.status}}✓ Success{{else}}✕ Fail{{/success}}: {{ repo.owner }}/{{ repo.name }} - Build #{{ build.number }}* (type: `{{ build.event }}`)
{{/if}}
Commit: <https://github.com/{{ repo.owner }}/{{ repo.name }}/commit/{{ build.commit }}|{{ truncate build.commit 8 }}>
Branch: <https://github.com/{{ repo.owner }}/{{ repo.name }}/commits/{{ build.branch }}|{{ build.branch }}>
Author: {{ build.author }}
<{{ build.link }}|Visit build page>'
2019-08-11 00:29:25 +03:00
},
};
local notify_steps = [notify];
2019-08-09 06:45:13 +03:00
local notify_trigger = {
trigger: {
2019-08-03 00:08:24 +03:00
status: ['success', 'failure'],
2019-08-09 06:45:13 +03:00
},
};
local notify_depends_on = {
2019-08-11 00:29:25 +03:00
depends_on: [
default_pipeline.name,
e2e_pipeline.name,
conformance_pipeline.name,
nightly_pipeline.name,
release_pipeline.name,
],
2019-08-09 06:45:13 +03:00
};
2019-12-23 21:36:14 +03:00
local notify_pipeline = Pipeline('notify', notify_steps, [default_pipeline, e2e_pipeline, conformance_pipeline, nightly_pipeline, release_pipeline], false, true) + notify_trigger;
2019-08-11 00:29:25 +03:00
// Final configuration file definition.
2019-08-09 06:45:13 +03:00
[
2019-12-23 21:36:14 +03:00
secret,
2019-08-09 06:45:13 +03:00
default_pipeline,
e2e_pipeline,
conformance_pipeline,
nightly_pipeline,
release_pipeline,
notify_pipeline,
]