0.5.2 · 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 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.

TipoPrivilégio
git-repositorybaixoum diretório, somente leitura
secret/git-tokenmédiotoken de acesso a repositório
secret/gcp-service-accountaltochave de service account
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.

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.