This PR updates the Collab deployment workflow to be generated with `cargo xtask workflows`. Release Notes: - N/A
Showing the changes to tooling (3 of 4 files). Show all
Unified · Split
| @@ -10,6 +10,7 @@ mod bump_patch_version; · 9 unmodified lines | ||
| 10 | 10 | mod cherry_pick; |
| 11 | 11 | mod compare_perf; |
| 12 | 12 | mod danger; |
| 13 | +mod deploy_collab; | |
| 13 | 14 | mod extension_bump; |
| 14 | 15 | mod extension_tests; |
| 15 | 16 | mod extension_workflow_rollout; |
| @@ -133,6 +134,7 @@ pub fn run_workflows(_: GenerateWorkflowArgs) -> Result<()> { · 117 unmodified lines | ||
| 133 | 134 | WorkflowFile::zed(cherry_pick::cherry_pick), |
| 134 | 135 | WorkflowFile::zed(compare_perf::compare_perf), |
| 135 | 136 | WorkflowFile::zed(danger::danger), |
| 137 | + WorkflowFile::zed(deploy_collab::deploy_collab), | |
| 136 | 138 | WorkflowFile::zed(extension_bump::extension_bump), |
| 137 | 139 | WorkflowFile::zed(extension_tests::extension_tests), |
| 138 | 140 | WorkflowFile::zed(extension_workflow_rollout::extension_workflow_rollout), |
| @@ -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 | +} | |
| @@ -30,6 +30,8 @@ secret!(AZURE_SIGNING_CLIENT_ID); · 29 unmodified lines | ||
| 30 | 30 | secret!(AZURE_SIGNING_CLIENT_SECRET); |
| 31 | 31 | secret!(AZURE_SIGNING_TENANT_ID); |
| 32 | 32 | secret!(CACHIX_AUTH_TOKEN); |
| 33 | +secret!(CLUSTER_NAME); | |
| 34 | +secret!(DIGITALOCEAN_ACCESS_TOKEN); | |
| 33 | 35 | secret!(DIGITALOCEAN_SPACES_ACCESS_KEY); |
| 34 | 36 | secret!(DIGITALOCEAN_SPACES_SECRET_KEY); |
| 35 | 37 | secret!(GITHUB_TOKEN); |