0.14.0 · em construção

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.

Um pipeline de dois steps: build e publish. A implementação do publish troca entre publish-gcp, publish-azure e publish-aws, apontando para GCP, Azure e AWS, enquanto o contrato permanece o mesmo. Em seguida a cena afasta e mostra o mesmo pipeline rodando num laptop, no GitLab CI e no GitHub Actions. Laptop GitLab CI GitHub Actions build docker-build-kaniko publish publish-gcp publish-azure publish-aws * GCP Azure AWS

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 dependência marcada sensitive 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: techlite
  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

Nada de linguagem preferida, API a implementar ou biblioteca do Oren dentro da sua imagem. A CLI monta as dependências, escreve as entradas em disco e lê a saída. É todo o protocolo:

# um worker completo, em shell
IMAGE=$(jq -r .imageName "$OREN_INPUT_PATH")
docker build -t "$IMAGE" /source
jq -n --arg image "$IMAGE" '{$image}' > "$OREN_OUTPUT_PATH"
# o mesmo worker, com as funções do oren.sh
. /oren/oren.sh

IMAGE=$(oren_input .imageName)
docker build -t "$IMAGE" /source
oren_output image "$IMAGE"

Nada além do protocolo: um arquivo de entrada, um de saída, e os caminhos nas variáveis. A outra aba usa o `oren.sh`, um arquivo shell que você copia para a imagem — nunca exigido, e que o motor não injeta.

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.

TipoPrivilégio
git-repositorybaixoum repositório git, conferido antes de rodar e montado só para leitura
directory mutable: truemédioescreve no seu diretório, e não só lê
secretmédiouma credencial — redigida em log e fora do lockfile
secret-filemédiouma credencial em arquivo — uma chave de service account, por exemplo
engine/dockercríticosocket 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-image escreve o step, resolve a implementação e aponta o que falta configurar.

  • Ou implemente

    oren init worker gera 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.

Pronto para agentes de IA

A pipeline roda onde o agente trabalha

Pipelines Oren rodam na máquina do agente: escrever, validate, run, corrigir — segundos por tentativa, sem push, sem fila, sem minutos de CI. E o controle de dados continua humano: o agente monta e executa, mas privilégio novo só entra com o seu oren authorize.

Adicione as skills para Claude Code ao seu projeto e comece com o prompt abaixo:

Crie uma pipeline Oren para build e testes deste repositório. Mantenha os
artefatos oren criados no próprio repositório (registro local comitado) para
usar o Oren sem custos, valide tudo com oren validate e rode localmente
antes de me mostrar o resultado.

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

Seu catálogo, suas contas, seus dados — nada sai da sua rede, e tasks privadas continuam privadas porque o servidor é seu.

Sem limite de artefatos privados e sem cobrança, sempre.

Como auto-hospedar

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.

No ar em registry.oren.sh, com o catálogo ainda em formação.

Ver planos

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. Usa o Oren para montar as pipelines de entrega dos clientes e dos produtos próprios — o sinuca.gg, e o próprio Oren, que se publica com ele. É também quem mantém os workers de referência sob techlite/*: analisar commits, construir e publicar imagens, Terraform, Cloud Deploy e Coolify. Uma entrega típica deriva a versão dos conventional commits, publica as imagens e cria a release — a partir do mesmo arquivo que roda na máquina de quem desenvolve.

Esta é a versão 0.14.0. Versões publicadas já são imutáveis, mas o formato do documento ainda pode mudar antes da 1.0.