---
title: "Cómo usar Taskfile como alternativa a Make en Ubuntu 24.04"
description: "Instala Task en Ubuntu 24.04 y automatiza tu proyecto con un Taskfile.yml: dependencias, variables, .env, precondiciones, includes y CI en GitHub Actions."
category: "Automatización Avanzada"
language: es
source: https://cubepath.com/es/docs/automatización-avanzada/taskfile-como-alternativa-a-makefile
updated: 2026-09-25
---
# Cómo usar Taskfile como alternativa a Make en Ubuntu 24.04
Task es un ejecutor de tareas escrito en Go que lee sus instrucciones de un archivo `Taskfile.yml`. Cubre el uso más habitual de Make (tener a mano los comandos de compilar, probar y desplegar un proyecto) con una sintaxis YAML legible, variables explícitas y sin las trampas de los tabuladores ni de los objetivos que coinciden con nombres de archivo. En este tutorial instalarás Task en Ubuntu 24.04 y construirás paso a paso un Taskfile para un proyecto de ejemplo.
Los ejemplos solo usan herramientas del sistema (`cp`, `tar`, `rsync`) para que puedas ejecutarlos sin instalar ningún lenguaje. En tu proyecto real sustituirás esos comandos por `go build`, `npm run build`, `pytest` o lo que corresponda.
## Requisitos previos
- Un servidor o equipo con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con un usuario no root con privilegios `sudo`.
- `git` instalado (algunas variables del ejemplo leen el commit actual).
- Conocimientos básicos de YAML y de la terminal.
## Paso 1: Instalar Task
El proyecto publica un paquete `.deb` en cada versión de GitHub. Descárgalo e instálalo con `apt`, que así queda registrado en el sistema y se puede desinstalar limpiamente:
```bash
cd /tmp
curl -fsSLO https://github.com/go-task/task/releases/latest/download/task_linux_amd64.deb
sudo apt install -y ./task_linux_amd64.deb
```
En servidores arm64 usa `task_linux_arm64.deb`. Si prefieres actualizaciones automáticas, Task también está disponible como snap con `sudo snap install task --classic`.
Comprueba la instalación:
```bash
task --version
```
```output
Task version: v3.x.y
```
> Nota: el binario se llama `task`. No lo confundas con Taskwarrior, un gestor de listas de tareas que también usa ese nombre en algunos repositorios.
Activa el autocompletado en bash añadiendo esta línea a tu `~/.bashrc`:
```bash
echo 'eval "$(task --completion bash)"' >> ~/.bashrc
source ~/.bashrc
```
## Paso 2: Crear el proyecto de ejemplo y el primer Taskfile
Crea un proyecto mínimo con un par de archivos fuente:
```bash
mkdir -p ~/demo-task/src && cd ~/demo-task
git init -q
echo '
Hola desde Task
' > src/index.html
echo 'body { font-family: sans-serif; }' > src/style.css
git add . && git commit -qm "Primer commit"
```
Crea el `Taskfile.yml` en la raíz del proyecto:
```bash
nano Taskfile.yml
```
```yaml
version: '3'
vars:
APP: demo-web
DIST: dist
tasks:
default:
desc: Mostrar las tareas disponibles
cmds:
- task --list
build:
desc: Copiar los fuentes a la carpeta de distribución
cmds:
- mkdir -p {{.DIST}}
- cp -r src/. {{.DIST}}/
clean:
desc: Borrar los archivos generados
cmds:
- rm -rf {{.DIST}} *.tar.gz
```
Las variables se referencian con la sintaxis de plantillas de Go, `{{.NOMBRE}}`. Solo las tareas con `desc` aparecen en `task --list`.
Lista y ejecuta las tareas:
```bash
task --list
task build
```
```output
task: Available tasks for this project:
* build: Copiar los fuentes a la carpeta de distribución
* clean: Borrar los archivos generados
* default: Mostrar las tareas disponibles
task: [build] mkdir -p dist
task: [build] cp -r src/. dist/
```
Task muestra cada comando antes de ejecutarlo con el prefijo `task: [nombre]`. Si un comando falla, la tarea se detiene con el mismo código de salida, igual que Make.
## Paso 3: Evitar trabajo repetido con sources y generates
Make decide si recompilar comparando fechas de archivos. Task hace lo mismo con `sources` y `generates`, pero por defecto compara sumas de verificación del contenido. Cambia la tarea `build`:
```yaml
build:
desc: Copiar los fuentes a la carpeta de distribución
sources:
- src/**/*
generates:
- '{{.DIST}}/index.html'
cmds:
- mkdir -p {{.DIST}}
- cp -r src/. {{.DIST}}/
```
Ejecuta la tarea dos veces seguidas:
```bash
task build
task build
```
```output
task: [build] mkdir -p dist
task: [build] cp -r src/. dist/
task: Task "build" is up to date
```
La segunda vez no hace nada porque los fuentes no han cambiado. Modifica `src/index.html` y vuelve a ejecutarla para ver que se repite. Para forzarla aunque esté al día, usa `task --force build`. Task guarda las sumas en el directorio `.task/`; añádelo a tu `.gitignore`.
## Paso 4: Encadenar tareas con dependencias
Una tarea puede depender de otras. Las indicadas en `deps` se ejecutan antes y **en paralelo**; si necesitas un orden estricto, llámalas desde `cmds` con `task:`. Añade una tarea que empaquete el resultado:
```yaml
package:
desc: Crear un tar.gz con la versión actual
deps: [build]
vars:
COMMIT:
sh: git rev-parse --short HEAD
cmds:
- tar -czf {{.APP}}-{{.COMMIT}}.tar.gz -C {{.DIST}} .
- ls -lh {{.APP}}-{{.COMMIT}}.tar.gz
```
La variable `COMMIT` es dinámica: su valor es la salida del comando indicado en `sh`. Ejecuta el empaquetado:
```bash
task package
```
```output
task: Task "build" is up to date
task: [package] tar -czf demo-web-a1b2c3d.tar.gz -C dist .
task: [package] ls -lh demo-web-a1b2c3d.tar.gz
-rw-rw-r-- 1 usuario usuario 312 sep 25 10:00 demo-web-a1b2c3d.tar.gz
```
Para ver qué haría una tarea sin ejecutarla, usa `task --dry package`.
## Paso 5: Variables desde la línea de comandos y desde .env
Las variables se pueden pasar al invocar Task, y tienen prioridad sobre las del Taskfile. Además, la clave `dotenv` carga archivos `.env` como variables de entorno.
Crea un archivo `.env` con el destino del despliegue:
```bash
echo 'DEPLOY_PATH=/tmp/demo-deploy' > .env
```
Añade `dotenv` al principio del Taskfile, justo después de `version`:
```yaml
version: '3'
dotenv: ['.env']
```
Y una tarea de despliegue que exige una variable `ENV`:
```yaml
deploy:
desc: Publicar dist en DEPLOY_PATH (uso, task deploy ENV=staging)
deps: [build]
requires:
vars: [ENV]
preconditions:
- sh: git diff --quiet
msg: Hay cambios sin confirmar en git. Haz commit antes de desplegar.
cmds:
- mkdir -p "$DEPLOY_PATH/{{.ENV}}"
- rsync -a --delete {{.DIST}}/ "$DEPLOY_PATH/{{.ENV}}/"
- echo "Desplegado {{.APP}} en $DEPLOY_PATH/{{.ENV}}"
```
- `requires.vars` detiene la tarea si falta la variable, con un mensaje claro.
- `preconditions` ejecuta comprobaciones previas; si alguna devuelve un código distinto de 0, muestra `msg` y aborta.
- `$DEPLOY_PATH` es una variable de entorno que viene del `.env`, por eso se usa con la sintaxis del shell.
Prueba primero sin la variable y después con ella:
```bash
task deploy
task deploy ENV=staging
```
```output
task: Task "deploy" cancelled because it is missing required variables: ENV
task: Task "build" is up to date
task: [deploy] mkdir -p "$DEPLOY_PATH/staging"
task: [deploy] rsync -a --delete dist/ "$DEPLOY_PATH/staging/"
task: [deploy] echo "Desplegado demo-web en $DEPLOY_PATH/staging"
Desplegado demo-web en /tmp/demo-deploy/staging
```
Si tienes cambios sin confirmar, la precondición lo impedirá. Añade `.task/`, `dist/`, `*.tar.gz` y `.env` a `.gitignore` y haz commit para que el árbol quede limpio.
## Paso 6: Ejecutar una tarea solo cuando haga falta con status
`status` es lo contrario de `preconditions`: si todos sus comandos terminan con éxito, la tarea se considera hecha y se omite. Es útil para pasos de preparación idempotentes:
```yaml
setup:
desc: Crear el .env a partir de la plantilla si no existe
status:
- test -f .env
cmds:
- cp .env.example .env
```
Con `.env` ya presente, `task setup` responde `task: Task "setup" is up to date` sin tocar nada.
## Paso 7: Dividir el Taskfile con includes
En proyectos grandes conviene separar las tareas por área. Crea un Taskfile para las tareas de servidor:
```bash
mkdir -p taskfiles
nano taskfiles/servidor.yml
```
```yaml
version: '3'
tasks:
espacio:
desc: Mostrar el espacio libre en disco
cmds:
- df -h /
servicios:
desc: Listar los servicios de systemd que han fallado
cmds:
- systemctl --failed --no-pager
```
Inclúyelo en el `Taskfile.yml` principal, al mismo nivel que `vars` y `tasks`:
```yaml
includes:
srv:
taskfile: ./taskfiles/servidor.yml
optional: true
```
Las tareas incluidas se invocan con el espacio de nombres como prefijo:
```bash
task srv:espacio
```
```output
task: [srv:espacio] df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 39G 4.2G 35G 11% /
```
Con `optional: true`, Task no falla si el archivo incluido no existe.
## Paso 8: Usar Task en GitHub Actions
Como el Taskfile es la única fuente de verdad de cómo se compila el proyecto, el pipeline de CI solo tiene que instalar Task y llamar a las mismas tareas que usas en local. Crea `.github/workflows/ci.yml`:
```yaml
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Instalar Task
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Empaquetar
run: task package
```
En otros sistemas de CI instala el `.deb` del paso 1 en la imagen del runner o usa una imagen que ya incluya `task`.
## Taskfile frente a Makefile
| Aspecto | Make | Task |
|---|---|---|
| Formato | Sintaxis propia, recetas con tabulador obligatorio | YAML |
| Recompilar solo si hay cambios | Por fecha de archivos | Por suma de verificación (o fecha, con `method: timestamp`) |
| Variables | Expansión en varias fases, difícil de depurar | Plantillas Go, dinámicas con `sh:` |
| Archivos `.env` | No | `dotenv` |
| Dependencias en paralelo | Con `make -j` | Por defecto en `deps` |
| Disponibilidad | Preinstalado en casi todos los sistemas | Hay que instalar un binario |
Si tu proyecto compila C o C++ y depende del grafo de archivos de Make, sigue con Make. Si lo usas solo como lista de comandos del proyecto, Task es más fácil de leer y mantener.
## Solución de problemas
**`task: No Taskfile found`.** Task busca `Taskfile.yml` (o `Taskfile.yaml`, `taskfile.yml`) en el directorio actual y en los superiores. Comprueba el nombre del archivo o indica la ruta con `task --taskfile ruta/Taskfile.yml`.
**Una variable aparece vacía.** Las variables del Taskfile y de la línea de comandos se usan con `{{.VAR}}`; las de entorno y las del `.env`, con `$VAR` dentro del comando. Revisa el comando final con `task --dry nombre`.
**La tarea dice `is up to date` pero quieres ejecutarla.** Usa `--force`, o borra el directorio `.task/` para reiniciar todas las sumas de verificación.
**Error de YAML al cargar el Taskfile.** Los valores que contienen `{{ }}` al principio o dos puntos deben ir entre comillas, por ejemplo `- '{{.DIST}}/index.html'`.
## Conclusión
Tienes Task instalado y un Taskfile que compila solo cuando cambian los fuentes, empaqueta con el commit actual, despliega con variables obligatorias y precondiciones, se divide en archivos incluidos y se reutiliza tal cual en CI. Como siguientes pasos, traslada los comandos de tu `Makefile` actual tarea por tarea, usa `task --summary nombre` para documentar las tareas más complejas y añade `task --list` al README del proyecto.