History

ci: Generate the Collab deployment workflow (#49306)

This PR updates the Collab deployment workflow to be generated with `cargo xtask workflows`. Release Notes: - N/A

Marshall Bowers committed 9 months ago

Commit 958798d1 parent 05940764 files · +311 −130Browse files

Showing the changes to tooling (3 of 4 files). Show all

Unified · Split

3 files
  1. tooling/xtask/src/tasks/workflows.rs +2 −0
  2. tooling/xtask/src/tasks/workflows/deploy_collab.rs +171 −0
  3. tooling/xtask/src/tasks/workflows/vars.rs +2 −0
tooling/xtask/src/tasks/workflows.rs+2−0
@@ -10,6 +10,7 @@ mod bump_patch_version; · 9 unmodified lines
1010 mod cherry_pick;
1111 mod compare_perf;
1212 mod danger;
13+mod deploy_collab;
1314 mod extension_bump;
1415 mod extension_tests;
1516 mod extension_workflow_rollout;
@@ -133,6 +134,7 @@ pub fn run_workflows(_: GenerateWorkflowArgs) -> Result<()> { · 117 unmodified lines
133134 WorkflowFile::zed(cherry_pick::cherry_pick),
134135 WorkflowFile::zed(compare_perf::compare_perf),
135136 WorkflowFile::zed(danger::danger),
137+ WorkflowFile::zed(deploy_collab::deploy_collab),
136138 WorkflowFile::zed(extension_bump::extension_bump),
137139 WorkflowFile::zed(extension_tests::extension_tests),
138140 WorkflowFile::zed(extension_workflow_rollout::extension_workflow_rollout),
tooling/xtask/src/tasks/workflows/deploy_collab.rs+171−0
@@ -0,0 +1,171 @@
1+use gh_workflow::{Container, Event, Port, Push, Run, Step, Use, Workflow};
2+use indoc::{formatdoc, indoc};
3+
4+use crate::tasks::workflows::{
5+ runners::{self, Platform},
6+ steps::{self, CommonJobConditions, NamedJob, dependant_job, named},
7+ vars,
8+};
9+
10+pub(crate) fn deploy_collab() -> Workflow {
11+ let style = style();
12+ let tests = tests(&[&style]);
13+ let publish = publish(&[&style, &tests]);
14+ let deploy = deploy(&[&publish]);
15+
16+ named::workflow()
17+ .on(Event::default().push(Push::default().add_tag("collab-production")))
18+ .add_env(("DOCKER_BUILDKIT", "1"))
19+ .add_job(style.name, style.job)
20+ .add_job(tests.name, tests.job)
21+ .add_job(publish.name, publish.job)
22+ .add_job(deploy.name, deploy.job)
23+}
24+
25+fn style() -> NamedJob {
26+ named::job(
27+ dependant_job(&[])
28+ .name("Check formatting and Clippy lints")
29+ .with_repository_owner_guard()
30+ .runs_on(runners::LINUX_XL)
31+ .add_step(steps::checkout_repo().add_with(("fetch-depth", 0)))
32+ .add_step(steps::setup_cargo_config(Platform::Linux))
33+ .add_step(steps::cache_rust_dependencies_namespace())
34+ .add_step(steps::cargo_fmt())
35+ .add_step(steps::clippy(Platform::Linux)),
36+ )
37+}
38+
39+fn tests(deps: &[&NamedJob]) -> NamedJob {
40+ fn run_collab_tests() -> Step<Run> {
41+ named::bash("cargo nextest run --package collab --no-fail-fast")
42+ }
43+
44+ named::job(
45+ dependant_job(deps)
46+ .name("Run tests")
47+ .runs_on(runners::LINUX_XL)
48+ .add_service(
49+ "postgres",
50+ Container::new("postgres:15")
51+ .add_env(("POSTGRES_HOST_AUTH_METHOD", "trust"))
52+ .ports(vec![Port::Name("5432:5432".into())])
53+ .options(
54+ "--health-cmd pg_isready \
55+ --health-interval 500ms \
56+ --health-timeout 5s \
57+ --health-retries 10",
58+ ),
59+ )
60+ .add_step(steps::checkout_repo().add_with(("fetch-depth", 0)))
61+ .add_step(steps::setup_cargo_config(Platform::Linux))
62+ .add_step(steps::cache_rust_dependencies_namespace())
63+ .add_step(steps::cargo_install_nextest())
64+ .add_step(steps::clear_target_dir_if_large(Platform::Linux))
65+ .add_step(run_collab_tests()),
66+ )
67+}
68+
69+fn publish(deps: &[&NamedJob]) -> NamedJob {
70+ fn install_doctl() -> Step<Use> {
71+ named::uses("digitalocean", "action-doctl", "v2")
72+ .add_with(("token", vars::DIGITALOCEAN_ACCESS_TOKEN))
73+ }
74+
75+ fn sign_into_registry() -> Step<Run> {
76+ named::bash("doctl registry login")
77+ }
78+
79+ fn build_docker_image() -> Step<Run> {
80+ named::bash(indoc! {r#"
81+ docker build -f Dockerfile-collab \
82+ --build-arg "GITHUB_SHA=$GITHUB_SHA" \
83+ --tag "registry.digitalocean.com/zed/collab:$GITHUB_SHA" \
84+ .
85+ "#})
86+ }
87+
88+ fn publish_docker_image() -> Step<Run> {
89+ named::bash(r#"docker push "registry.digitalocean.com/zed/collab:${GITHUB_SHA}""#)
90+ }
91+
92+ fn prune_docker_system() -> Step<Run> {
93+ named::bash("docker system prune --filter 'until=72h' -f")
94+ }
95+
96+ named::job(
97+ dependant_job(deps)
98+ .name("Publish collab server image")
99+ .runs_on(runners::LINUX_XL)
100+ .add_step(install_doctl())
101+ .add_step(sign_into_registry())
102+ .add_step(steps::checkout_repo())
103+ .add_step(build_docker_image())
104+ .add_step(publish_docker_image())
105+ .add_step(prune_docker_system()),
106+ )
107+}
108+
109+fn deploy(deps: &[&NamedJob]) -> NamedJob {
110+ fn install_doctl() -> Step<Use> {
111+ named::uses("digitalocean", "action-doctl", "v2")
112+ .add_with(("token", vars::DIGITALOCEAN_ACCESS_TOKEN))
113+ }
114+
115+ fn sign_into_kubernetes() -> Step<Run> {
116+ named::bash(formatdoc! {r#"
117+ doctl kubernetes cluster kubeconfig save --expiry-seconds 600 {cluster_name}
118+ "#, cluster_name = vars::CLUSTER_NAME})
119+ }
120+
121+ fn start_rollout() -> Step<Run> {
122+ named::bash(indoc! {r#"
123+ set -eu
124+ if [[ $GITHUB_REF_NAME = "collab-production" ]]; then
125+ export ZED_KUBE_NAMESPACE=production
126+ export ZED_COLLAB_LOAD_BALANCER_SIZE_UNIT=10
127+ export ZED_API_LOAD_BALANCER_SIZE_UNIT=2
128+ elif [[ $GITHUB_REF_NAME = "collab-staging" ]]; then
129+ export ZED_KUBE_NAMESPACE=staging
130+ export ZED_COLLAB_LOAD_BALANCER_SIZE_UNIT=1
131+ export ZED_API_LOAD_BALANCER_SIZE_UNIT=1
132+ else
133+ echo "cowardly refusing to deploy from an unknown branch"
134+ exit 1
135+ fi
136+
137+ echo "Deploying collab:$GITHUB_SHA to $ZED_KUBE_NAMESPACE"
138+
139+ source script/lib/deploy-helpers.sh
140+ export_vars_for_environment $ZED_KUBE_NAMESPACE
141+
142+ ZED_DO_CERTIFICATE_ID="$(doctl compute certificate list --format ID --no-header)"
143+ export ZED_DO_CERTIFICATE_ID
144+ export ZED_IMAGE_ID="registry.digitalocean.com/zed/collab:${GITHUB_SHA}"
145+
146+ export ZED_SERVICE_NAME=collab
147+ export ZED_LOAD_BALANCER_SIZE_UNIT=$ZED_COLLAB_LOAD_BALANCER_SIZE_UNIT
148+ export DATABASE_MAX_CONNECTIONS=850
149+ envsubst < crates/collab/k8s/collab.template.yml | kubectl apply -f -
150+ kubectl -n "$ZED_KUBE_NAMESPACE" rollout status deployment/$ZED_SERVICE_NAME --watch
151+ echo "deployed ${ZED_SERVICE_NAME} to ${ZED_KUBE_NAMESPACE}"
152+
153+ export ZED_SERVICE_NAME=api
154+ export ZED_LOAD_BALANCER_SIZE_UNIT=$ZED_API_LOAD_BALANCER_SIZE_UNIT
155+ export DATABASE_MAX_CONNECTIONS=60
156+ envsubst < crates/collab/k8s/collab.template.yml | kubectl apply -f -
157+ kubectl -n "$ZED_KUBE_NAMESPACE" rollout status deployment/$ZED_SERVICE_NAME --watch
158+ echo "deployed ${ZED_SERVICE_NAME} to ${ZED_KUBE_NAMESPACE}"
159+ "#})
160+ }
161+
162+ named::job(
163+ dependant_job(deps)
164+ .name("Deploy new server image")
165+ .runs_on(runners::LINUX_XL)
166+ .add_step(steps::checkout_repo())
167+ .add_step(install_doctl())
168+ .add_step(sign_into_kubernetes())
169+ .add_step(start_rollout()),
170+ )
171+}
tooling/xtask/src/tasks/workflows/vars.rs+2−0
@@ -30,6 +30,8 @@ secret!(AZURE_SIGNING_CLIENT_ID); · 29 unmodified lines
3030 secret!(AZURE_SIGNING_CLIENT_SECRET);
3131 secret!(AZURE_SIGNING_TENANT_ID);
3232 secret!(CACHIX_AUTH_TOKEN);
33+secret!(CLUSTER_NAME);
34+secret!(DIGITALOCEAN_ACCESS_TOKEN);
3335 secret!(DIGITALOCEAN_SPACES_ACCESS_KEY);
3436 secret!(DIGITALOCEAN_SPACES_SECRET_KEY);
3537 secret!(GITHUB_TOKEN);