CI/CD para Rust: Automatización de compilación y despliegue desde cero

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué tu proyecto Rust merece un CI/CD real?

\n\n

Imagina: escribes en Rust, el compilador es tu mejor amigo, el borrow checker no te deja relajarte y el código funciona a la velocidad del rayo. Pero cuando llega el momento del despliegue, la magia termina. Ejecutar pruebas manualmente, compilar en tu máquina local, subir el binario al servidor mediante SCP: ese es un camino a ninguna parte. Especialmente cuando el proyecto crece y aparece un segundo desarrollador en el equipo.

\n\n

CI/CD (Integración Continua / Despliegue Continuo) no es solo una palabra de moda. Es un sistema que se encarga de la rutina: ejecutar pruebas, verificar el estilo del código, compilar la versión de lanzamiento y enviarla a donde debe funcionar. Para Rust, con su énfasis en la confiabilidad y el rendimiento, la automatización de la compilación es una extensión natural de la filosofía del lenguaje.

\n\n

En este artículo, configuraremos desde cero un pipeline CI/CD para una aplicación Rust en GitHub Actions. Aprenderás a organizar pruebas, linting, compilación de binarios para diferentes plataformas y despliegue. Todo con ejemplos de código reales que puedes copiar a tu proyecto.

\n\n

¿Qué vamos a automatizar?

\n\n

Antes de escribir código, definamos los objetivos. Nuestro pipeline hará cuatro cosas:

\n\n
    \n
  • Linting y formateo — para que el código cumpla con los estándares de Rust y no contenga errores típicos.
  • \n
  • Pruebas — ejecución de todas las pruebas unitarias y, si las hay, de integración.
  • \n
  • Compilación del binario — compilación de la versión optimizada (release).
  • \n
  • Despliegue — carga del artefacto compilado al servidor o a los lanzamientos de GitHub.
  • \n
\n\n

Todo esto ocurrirá automáticamente con cada push a la rama main o al crear un pull request. ¿Suena a magia? En realidad, solo son archivos YAML y un par de comandos de Cargo.

\n\n

Paso 1: Preparación del proyecto

\n\n

Como ejemplo, tomaremos un servidor web simple con Actix-web. Pero el pipeline es universal: sirve para cualquier proyecto Rust, ya sea una utilidad CLI, una biblioteca o un microservicio.

\n\n

Creemos un nuevo proyecto:

\n\n
cargo new rust-ci-cd-demo --bin\ncd rust-ci-cd-demo
\n\n

Añadamos las dependencias en Cargo.toml:

\n\n
[dependencies]\nactix-web = "4"\nserde = { version = "1", features = ["derive"] }
\n\n

Y el código más simple en src/main.rs:

\n\n
use actix_web::{get, App, HttpResponse, HttpServer, Responder};\n\n#[get("/")]\nasync fn hello() -> impl Responder {\n    HttpResponse::Ok().body("Hello from Rust CI/CD!")\n}\n\n#[actix_web::main]\nasync fn main() -> std::io::Result<()> {\n    HttpServer::new(|| {\n        App::new().service(hello)\n    })\n    .bind(("0.0.0.0", 8080))?\n    .run()\n    .await\n}
\n\n

Añadamos una prueba simple en src/main.rs (al final del archivo):

\n\n
#[cfg(test)]\nmod tests {\n    use actix_web::{test, App, web};\n    use crate::hello;\n\n    #[actix_web::test]\n    async fn test_hello_endpoint() {\n        let app = test::init_service(App::new().service(hello)).await;\n        let req = test::TestRequest::get().uri("/").to_request();\n        let resp = test::call_service(&app, req).await;\n        assert!(resp.status().is_success());\n    }\n}
\n\n

Todo listo. Ahora viene lo interesante: la configuración de CI/CD.

\n\n

Paso 2: Crear el workflow de GitHub Actions

\n\n

GitHub Actions es la herramienta CI/CD integrada de GitHub. Funciona con archivos YAML que se encuentran en el directorio .github/workflows/. Creémoslo:

\n\n
mkdir -p .github/workflows\ntouch .github/workflows/ci.yml
\n\n

Abramos ci.yml y empecemos a escribir el pipeline. Lo llamaremos "Rust CI/CD Pipeline".

\n\n

Disparador básico y entorno

\n\n
name: Rust CI/CD Pipeline\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\nenv:\n  CARGO_TERM_CO                

Blogs

Book Recommendations