Escreva uma task uma vez.
Rode em qualquer lugar.
Toda equipe reescreve as mesmas dez pipelines. Build, tag, push, deploy — o mesmo trabalho, copiado entre projetos e empresas, e depois traduzido de novo para o YAML de cada CI. O Oren transforma cada etapa em um contrato: entradas, saídas e dependências declaradas, com implementações intercambiáveis — que rodam idêntico no seu laptop, no GitLab, no GitHub ou no Cloud Build.
O problema
Reaproveitar pipeline hoje é copiar e colar
"Analisar commits e decidir a próxima versão" é a mesma tarefa em qualquer repositório do mundo. Mas cada equipe a reescreve do zero, presa às primitivas do seu CI, sem forma de dizer o que ela recebe e o que devolve.
Sem contrato, não há substituição possível: trocar a implementação significa reescrever o pipeline. Não há comparação possível: duas soluções para o mesmo problema não são comparáveis se nem descrevem o mesmo problema. E não há reaproveitamento entre organizações, porque não existe nada para reaproveitar além de um arquivo YAML.
Portabilidade
O pipeline não pertence ao seu CI
Um pipeline escrito em GitLab CI só roda no GitLab. Reproduzi-lo na sua máquina significa adivinhar o que o runner faz, e migrar de plataforma significa reescrever tudo. No Oren o pipeline é um arquivo só, e onde ele roda é uma decisão separada.
# na sua máquina, igual ao que roda em produção oren run dev # ou gere a configuração nativa da sua plataforma oren generate gitlab > .gitlab-ci.yml oren generate github > .github/workflows/ci.yml oren generate cloudbuild > cloudbuild.yaml
Os dois caminhos executam exatamente os mesmos containers, com os mesmos contratos.
Local primeiro
Rode o pipeline inteiro antes de fazer commit. Sem push de teste, sem esperar fila de runner para descobrir um erro de digitação.
Nativo quando quiser
A geração produz um job por step, aproveitando paralelismo, cache e a interface da plataforma — sem você escrever o YAML dela.
Sem lock-in
Trocar de GitLab para GitHub, ou de nuvem, não reescreve o pipeline. Só muda o alvo da geração.
Isso funciona porque as dependências são tipadas. O gerador sabe que uma
secret/gcp-service-account vira uma variável protegida no GitLab, um secret no
GitHub Actions ou uma referência ao Secret Manager no Cloud Build. Um caminho de arquivo solto
não daria essa informação a ninguém.
A ideia
Uma task é um contrato. Um worker é uma das formas de cumpri-lo.
O contrato declara o que entra, o que sai e de que recursos do ambiente a task precisa — e nada sobre como o trabalho é feito. Isso é escolha de cada implementação, e é por isso que elas podem ser trocadas sem que o pipeline mude uma linha.
# o contrato — publicado uma vez apiVersion: oren.sh/v1 kind: Task metadata: name: analyze-commits namespace: oren version: 1.0.0 spec: inputs: properties: defaultChange: type: string enum: [major, minor, patch, none] outputs: properties: change: { type: string } minor: { type: boolean } dependencies: source: type: git-repository
O contrato não menciona linguagem, imagem nem caminho.
# o pipeline, no seu repositório steps: - id: analyze task: techlite/analyze-commits@^1.0.0 inputs: defaultChange: minor dependencies: source: "." - id: build task: techlite/build-docker-image@^1.0.0 inputs: imageName: acme/api incrementMinor: ${outputs['analyze'].minor} dependencies: source: "."
A saída de uma task é a entrada da próxima, com tipos verificados.
Execução
Um worker é uma imagem que lê um arquivo e escreve outro
Não há SDK obrigatório, linguagem preferida nem API a implementar. A CLI monta as dependências, escreve as entradas em disco e lê a saída. É todo o protocolo:
# um worker completo, em shell . /oren/oren.sh IMAGE=$(oren_input .imageName) docker build -t "$IMAGE" /source oren_output image "$IMAGE"
A primeira linha carrega o SDK, um arquivo shell copiado para a imagem — não há nada injetado. stdout e stderr ficam livres para log: não carregam dados.
Isolado
Tudo roda em container, orquestrado por Dagger. Nada é instalado na máquina de quem executa.
Reprodutível
Um oren.lock trava contrato, implementação e digest da imagem. O mesmo pipeline hoje e daqui a um ano.
Verificado
Entradas e saídas são validadas contra o contrato. Saída fora do formato falha o step, mesmo com exit code zero.
Dependências
O que uma task pede do seu ambiente fica explícito
Pastas, credenciais e acesso ao Docker não são detalhes de configuração — são o custo de rodar aquele worker na sua máquina. Cada dependência é declarada e tipada, e a CLI concede exatamente o que foi declarado. Nada além.
| Tipo | Privilégio | |
|---|---|---|
git-repository | baixo | um diretório, somente leitura |
secret/git-token | médio | token de acesso a repositório |
secret/gcp-service-account | alto | chave de service account |
engine/docker | crítico | socket do daemon — equivale a root no host |
Isso torna duas implementações do mesmo contrato realmente comparáveis. Se ambas constroem a mesma imagem e uma exige o socket do Docker enquanto a outra usa kaniko, a diferença deixa de ser invisível — e a escolha passa a ser informada.
Credenciais não precisam ser cadastradas em lugar nenhum. Se a sua organização já usa Vault ou Secret Manager, buscar o segredo é apenas mais uma task no início do pipeline. Valores marcados como sensíveis nunca aparecem em log, nunca vão para o lockfile e nunca tocam o disco da máquina.
Portal
Um catálogo aberto entre organizações
Contratos publicados por uma organização podem ser implementados por qualquer outra. É o que impede o problema original de voltar em outra escala: se cada empresa precisasse escrever o próprio contrato, estaríamos de novo com dez versões da mesma coisa.
-
Descubra
Encontre a task que faz o que você precisa e compare as implementações disponíveis lado a lado.
-
Adicione
oren add techlite/build-docker-imageescreve o step, resolve a implementação e aponta o que falta configurar. -
Ou implemente
oren init workergera a task inteira — contrato, worker, implementação e um pipeline de exemplo — em shell ou Node.
Versões publicadas são imutáveis e nunca desaparecem, só são depreciadas. Implementações privadas continuam possíveis para quem tem processo interno a proteger, mantendo o contrato público — e com ele a comparabilidade.
Começar
Três comandos
# a CLI npm install -g @oren-sh/cli # um projeto, e uma task do catálogo oren init oren add techlite/analyze-commits # roda na sua máquina, com o mesmo arquivo que roda no CI oren run dev
Para publicar as suas, oren login e oren publish. Os workers de
referência estão em oren/*. Quem publica um contrato não escolhe quem o
implementa — qualquer organização pode, e é isso que dá alternativa a quem consome.
Como usar
Duas formas, e a CLI é a mesma
O oren.yaml não muda entre elas. O que muda é onde o catálogo mora — e o
oren.lock garante que, depois de resolvido, executar não depende de catálogo
nenhum.
Na sua infraestrutura
on-premise · gratuito
Um jar e um Postgres. Seu catálogo, suas contas, seus dados — nada sai da sua rede, e tasks privadas continuam privadas porque o servidor é seu.
É o mesmo software, sem versão reduzida. Disponível agora.
Hospedado por nós
gerenciado · gratuito para tasks públicas
Sem servidor para manter. Publique no catálogo aberto e use o que outras organizações publicaram — um contrato pode ser implementado por qualquer uma delas, e é isso que dá alternativa a quem consome.
Ainda não está no ar.
Também dá para usar sem catálogo nenhum: tasks vindas de um diretório do seu repositório, resolvidas por caminho. É como se escreve um worker antes de publicá-lo.
Quem usa
Em produção hoje
Techlite. Mantém e publica os workers de referência sob
techlite/* — analisar commits, construir e publicar imagens, Terraform, Cloud
Deploy — e roda pipelines de entrega montados com eles: versão derivada de conventional
commits, duas imagens publicadas no Artifact Registry e uma release criada pelo Cloud Deploy,
a partir do mesmo arquivo que roda na máquina de quem desenvolve.
Esta é a versão 0.5.2. Versões publicadas já são imutáveis, mas o formato do documento ainda pode mudar antes da 1.0.