Escreva Dockerfiles e pipelines de CI em TypeScript.
Trellis é uma ferramenta CI/CD portátil. Com o Trellis, você pode definir seus Dockerfiles e pipelines de CI/CD em TypeScript e executá-los em qualquer lugar (localmente ou em uma plataforma hospedada).
Primeiro, instale o Deno com brew install deno
(ou comparável).
Segundo, instale o Trellis CLI com:
deno install
--allow-run=docker
--allow-net
--allow-write
--allow-env
--allow-read
https://deno.land/x/[email protected]/cli.ts
Execute trellis --help
para verificar sua instalação:
>>> trellis --help
Usage: trellis build mod.ts
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
ls [file] List all Images and Tasks available in a
TypeScript module
preview [options] [file] Generate a Dockerfile defined in a TypeScript
module
build [options] [file] Build an Image defined in a TypeScript module
run [options] [file] Run a Task defined in a TypeScript module
help [command] display help for command
Exporte qualquer Image
para permitir a geração de Dockerfile e construção de imagens com Trellis.
Por exemplo, para definir uma imagem do Ubuntu com alguns utilitários úteis instalados, você pode escrever o seguinte arquivo mod.ts
:
import { Image } from "https://deno.land/x/[email protected]/mod.ts" ;
const UBUNTU_VERSION = "20.04" ;
export const buildStage = Image . from ( `ubuntu: ${ UBUNTU_VERSION } ` )
. workDir ( "/root" )
. aptInstall ( [
"curl" ,
"jq" ,
"git" ,
] ) ;
A execução de trellis ls mod.ts
lista as imagens edificáveis:
>>> trellis ls mod.ts
Images:
- buildStage (trellis build --target buildStage)
Podemos visualizar o Dockerfile gerado com trellis preview mod.ts --target buildStage
:
>>> trellis preview --target buildStage
# syntax=docker/dockerfile:1.4
FROM ubuntu:20.04 AS stage-0
WORKDIR /root
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked --mount=type=cache,target=/var/lib/apt,sharing=locked apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends curl git jq
Podemos construir a imagem com trellis build --target buildStage
:
>>> trellis build --target buildStage
[+] Building 0.6s (11/11) FINISHED
= > [internal] load build definition from Dockerfile 0.0s
= > = > transferring dockerfile: 335B 0.0s
= > [internal] load .dockerignore 0.0s
= > = > transferring context: 2B 0.0s
= > resolve image config for docker.io/docker/dockerfile:1.4 0.2s
= > CACHED docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbf 0.0s
= > [internal] load build definition from Dockerfile 0.0s
= > [internal] load .dockerignore 0.0s
= > [internal] load metadata for docker.io/library/ubuntu:20.04 0.2s
= > [stage-0 1/3] FROM docker.io/library/ubuntu:20.04@sha256:35ab2bf57814e9ff49e365efd5a5935b6915ee 0.0s
= > CACHED [stage-0 2/3] WORKDIR /root 0.0s
= > CACHED [stage-0 3/3] RUN --mount=type=cache,target=/var/cache/apt,sharing=locked --mount=type=c 0.0s
= > exporting to image 0.0s
= > = > exporting layers 0.0s
= > = > writing image sha256:17f750ba9a4becf38ce4d584d0de4793bfd6a8139674c3b332cdcdf6525ea8d9 0.0s
= > = > naming to docker.io/trellis/db112e211de238c035a9fd3bbcbd5c417aafc5ee96a8c24d99d4caf81a759903 0.0s
√ Build: trellis/db112e211de238c035a9fd3bbcbd5c417aafc5ee96a8c24d99d4caf81a759903
Exporte qualquer função de um módulo TypeScript para permitir a execução de tarefas com Trellis.
Por exemplo, para definir um pipeline de CI para verificar se nossos utilitários de linha de comando foram instalados com êxito, você pode escrever o seguinte arquivo tasks.ts
:
import { build , Image , run } from "https://deno.land/x/[email protected]/mod.ts" ;
import { buildStage } from "./mod.ts" ;
export default async function runChecks ( ) {
await build ( buildStage ) ;
const checkCurl = Image . from ( buildStage ) . run (
"curl --help" ,
) ;
const checkJq = Image . from ( buildStage ) . run (
"jq --help" ,
) ;
const checkGit = Image . from ( buildStage ) . run (
"git --help" ,
) ;
await Promise . all ( [
run ( checkCurl ) ,
run ( checkJq ) ,
run ( checkGit ) ,
] ) ;
}
A execução de trellis ls tasks.ts
lista as tarefas executáveis:
>>> trellis ls tasks.ts
Tasks:
- default (trellis run tasks.ts)
Podemos executar a tarefa localmente com trellis run tasks.ts
:
>>> trellis run tasks.ts
[+] Building 1.1s (13/13) FINISHED
= > [internal] load build definition from Dockerfile 0.0s
= > = > transferring dockerfile: 335B 0.0s
= > [internal] load .dockerignore 0.0s
= > = > transferring context: 2B 0.0s
= > resolve image config for docker.io/docker/dockerfile:1.4 0.5s
= > [auth] docker/dockerfile:pull token for registry-1.docker.io 0.0s
= > CACHED docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbf 0.0s
= > [internal] load .dockerignore 0.0s
= > [internal] load build definition from Dockerfile 0.0s
= > [internal] load metadata for docker.io/library/ubuntu:20.04 0.3s
= > [auth] library/ubuntu:pull token for registry-1.docker.io 0.0s
= > [stage-0 1/3] FROM docker.io/library/ubuntu:20.04@sha256:35ab2bf57814e9ff49e365efd5a5935b6915ee 0.0s
= > CACHED [stage-0 2/3] WORKDIR /root 0.0s
= > CACHED [stage-0 3/3] RUN --mount=type=cache,target=/var/cache/apt,sharing=locked --mount=type=c 0.0s
= > exporting to image 0.0s
= > = > exporting layers 0.0s
= > = > writing image sha256:17f750ba9a4becf38ce4d584d0de4793bfd6a8139674c3b332cdcdf6525ea8d9 0.0s
= > = > naming to docker.io/trellis/adf8a603d1ab539848d89f68491e1b9213c1ca498f3f68d871e1b59c4c7de601 0.0s
√ Build: trellis/adf8a603d1ab539848d89f68491e1b9213c1ca498f3f68d871e1b59c4c7de601
√ Run: git --help
√ Run: jq --help
√ Run: curl --help
O Trellis pode ser configurado por meio de um arquivo trellis.config.ts
, cuja semântica básica é modelada a partir do Vite.
O trellis.config.ts
deve conter uma única exportação padrão que consiste em uma invocação defineConfig
, como esta:
import { defineConfig } from "https://deno.land/x/[email protected]/mod.ts" ;
export default defineConfig ( {
engine : "docker" ,
} ) ;
O Trellis usará o trellis.config.ts
mais próximo, procurando primeiro no diretório de trabalho atual e depois em cada diretório pai subsequente.
Trellis é compatível com depot.dev, que pode ser usado para permitir compilações aceleradas em nuvem sem configuração. Execute a instalação do Depot ( brew install depot/tap/depot
ou similar, seguido por depot login
) e defina um trellis.config.ts
assim:
import { defineConfig } from "https://deno.land/x/[email protected]/mod.ts" ;
export default defineConfig ( {
engine : {
type : "depot" ,
project : "${YOUR_PROJECT_ID}" ,
} ,
} ) ;
A partir daí, todas as compilações do Trellis serão executadas no Depot.
O Trellis é executado no Deno, tornando-o uma instalação em uma etapa no GitHub Actions:
name : CI
on :
push :
branches : [ main ]
pull_request :
branches : [ main ]
env :
DOCKER_BUILDKIT : 1
jobs :
build :
name : " Build "
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- name : " Install Deno "
uses : denoland/setup-deno@v1
with :
deno-version : " 1.25.2 "
- name : " Install Trellis "
working-directory : ./trellis
run : deno install --allow-run=docker --allow-net --allow-write --allow-env --allow-read https://deno.land/x/[email protected]/cli.ts
- name : " Build the image "
working-directory : ./examples/typescript
run : trellis build trellis/mod.ts
Trellis é motivado pelas seguintes observações, extraídas da experiência de manutenção de grandes sistemas CI/CD conteinerizados.
Dockerfiles são difíceis de manter . Com o tempo, grandes sistemas tendem a acumular coleções de Dockerfiles com subseções semelhantes, mas sem abstrações compartilhadas.
Dockerfiles eficientes são difíceis de escrever . Escrever um Dockerfile com capacidade máxima de armazenamento em cache e com um espaço ocupado mínimo requer conhecimento significativo. Por exemplo, para apt-get install
, a documentação do Docker recomenda o seguinte:
RUN apt-get update && apt-get install -y
# Be sure to sort dependencies to maximize cacheability.
bzr
cvs
git
mercurial
subversion
# Clear the apt cache to minimize disk size.
&& rm -rf /var/lib/apt/lists/ *
O loop de iteração CI/CD é muito lento . O fluxo de trabalho comum para escrever um novo pipeline de ações do GitHub, Jenkinsfile, etc., é confirmar, enviar por push, esperar que o sistema reconheça sua alteração e, em seguida, esperar que sua tarefa falhe – dezenas ou até centenas de vezes seguidas. Com as soluções de CI existentes, você escreve código para execução em um sistema desconhecido, fora do seu controle, sem um fluxo de trabalho de desenvolvimento de primeira classe.
Os sistemas CI/CD criam um aprisionamento significativo . Portar seus arquivos Jenkinsfiles ou YAML para GitHub Actions, ou vice-versa, requer lidar com abstrações específicas da plataforma.
O Trellis resolve esses problemas por meio de algumas decisões de design significativas.
Primeiro: com o Trellis, você define seus Dockerfiles e pipelines de CI/CD em TypeScript. Isso lhe dá o poder de uma linguagem de programação “completa”, mantendo uma API declarativa. Com TypeScript, obtemos os seguintes benefícios:
apt-get install
manualmente.deno.land
. Segundo: o Trellis torna a execução local uma primitiva de primeira classe. CI/CD não deve parecer um sistema totalmente separado; deve ser como executar código. Trellis é construído em Deno e altamente portátil. Você pode executar trellis build
localmente, assim como faria no GitHub Actions ou em outro lugar. Dessa forma, Trellis se inspira em ferramentas como Earthly e Dagger.
Trellis tem alguns objetivos ambiciosos que ainda não foram realizados:
Trellis é uma biblioteca e uma interface de linha de comando. Com o Trellis, você exporta definições Image
e funções executáveis (chamadas de "Tarefas") de seus módulos TypeScript e, em seguida, executa-as por meio da CLI trellis
.
trellis preview
Gere um Dockerfile definido em um módulo TypeScript.
Usage: trellis preview [options] [file]
Generate a Dockerfile defined in a TypeScript module
Options:
-t, --target < TARGET > Image to build within the TypeScript module
-h, --help display help for command
trellis build
Construa uma imagem definida em um módulo TypeScript.
Usage: trellis build [options] [file]
Build an Image defined in a TypeScript module
Options:
-t, --target < TARGET > Image to build within the TypeScript module
--push Whether to push the image to a remote registry
-h, --help display help for command
trellis ls
Liste todas as imagens e tarefas disponíveis em um módulo TypeScript.
Usage: trellis ls [options] [file]
List all Images and Tasks available in a TypeScript module
Options:
-h, --help display help for command
trellis run
Execute uma tarefa definida em um módulo TypeScript.
Run a Task defined in a TypeScript module
Options:
-t, --target <TARGET> Task to run within the TypeScript module
-h, --help display help for command
O diretório ./examples
demonstra uma variedade de casos de uso para Trellis. O Trellis é flexível e pode ser usado exclusivamente para gerar Dockerfiles para outros sistemas ou para definir pipelines inteiros de CI/CD.
rocket
: Um servidor web Rust no topo da estrutura Rocket. Demonstra compilações e implantação em vários estágios por meio do Fly.io, aproveitando trellis preview
.ruff
: Uma ferramenta de linha de comando Rust. Demonstra compilações eficientes e verificações de CI.runc
: um contêiner de desenvolvimento Linux. Demonstra a geração de artefatos com o Trellis e a cópia deles de volta para a máquina host.turborepo
: exemplo Docker do próprio Turborepo, modificado para gerar Dockerfiles com Trellis.typescript
: um monorepo TypeScript. Demonstra compilações eficientes e verificações de CI, juntamente com a consolidação de constantes (como a lista de espaços de trabalho TypeScript).wasm
: Um "Olá, mundo!" Binário Rust compilado no Wasm e testado no Wasmtime. O Trellis é construído no Deno, que é distribuído como um único executável binário sem dependências externas. Usar Deno significa que instalar o Trellis em qualquer lugar ) é tão simples quanto deno install ...
- não há package.json
, npm install
e nenhuma etapa de transpilação TypeScript.
Semelhante ao Nixpacks, o Trellis gera Dockerfiles. Isso simplifica a implementação do Trellis, mas também permite que os usuários aproveitem o Trellis apenas para geração de Dockerfile, em vez de como uma solução completa de CI/CD.
trellis build
e trellis run
dependem do Docker e assumem que o daemon do Docker é acessível localmente.
MIT