Primeiro projeto
Existem duas formas de rodar uma aplicação Pipevine. Elas não mudam nada no YAML em si — só como ele roda. Escolha uma antes de começar.
Duas formas de rodar
Com Program.cs (desenvolvimento local)
Um projeto Exe normal, com PackageReferences aos pacotes Pipevine.* e um host de poucas
linhas:
<!-- MinhaApi.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Pipevine.Sdk" Version="0.0.0-*" />
<PackageReference Include="Pipevine.Hosting.Http" Version="0.0.0-*" />
<PackageReference Include="Pipevine.Expressions.Jsonata" Version="0.0.0-*" />
<!-- só se usar persistência: -->
<PackageReference Include="Pipevine.Data.PostgreSql" Version="0.0.0-*" />
<!-- só se usar auth: -->
<PackageReference Include="Pipevine.Security.Jwt" Version="0.0.0-*" />
</ItemGroup>
<ItemGroup>
<None Include="*.pipevine.yaml" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddPipevine();
builder.Services.AddPipevineJsonata();
// AddPipevineJwt() precisa vir ANTES de AddPipevineHttp() quando você usa jwt.
builder.Services.AddPipevineJwt();
builder.Services.AddPipevineHttp();
builder.Services.AddPipevineData();
builder.Services.AddPipevinePostgreSql();
var app = builder.Build();
app.UseExceptionHandler();
app.UsePipevineCorrelation();
app.MapPipevineApps();
app.MapPipevineHealthChecks();
app.Run();
Um nuget.config restrito às fontes de pacote que você realmente usa (nuget.org mais qualquer
feed privado) evita ambiguidade de resolução de pacotes.
Sem Program.cs (conteinerizado)
Nenhum projeto C#. Só o YAML, rodando na imagem base genérica de host do Pipevine:
# docker-compose.yml
services:
api:
image: pipevine/hosting-generic:latest
ports: ["8080:8080"]
environment:
PIPEVINE_PG_CONNECTION: "Host=postgres;Port=5432;Database=minhaapi;Username=postgres;Password=postgres"
volumes:
- ./minha-api.pipevine.yaml:/app/config/minha-api.pipevine.yaml:ro
O host genérico descobre sozinho quais pacotes usar (Postgres, JWT etc.) a partir do que o próprio YAML declara — nenhum código de aplicação em nenhum dos dois casos. Um pacote de terceiro que implemente o mecanismo de descoberta de módulos do host, solto num diretório de plugins montado, é descoberto e registrado automaticamente da mesma forma.
Cuidado ao montar volumes. A variável que aponta para onde o host genérico procura arquivos
*.pipevine.yamlescaneia o diretório montado recursivamente. Monte só o arquivo YAML em si, nunca um diretório de projeto inteiro — uma pasta combin/objdentro faz o host encontrar cópias duplicadas do mesmo YAML (por exemplo, uma embin/Release/...) e registrar a mesma aplicação mais de uma vez. Veja mais em Implantação.
O esqueleto mínimo
# minha-api.pipevine.yaml
apiVersion: pipevine.dev/v1
kind: Application
metadata: { name: minha-api, version: 1.0.0 }
spec:
type: api
routes:
- id: ping
method: GET
path: /ping
anonymous: true
pipeline:
- type: return
response:
status: 200
body: "'pong'"
Isso já sobe — de qualquer uma das duas formas acima — e responde GET /ping com "pong".
anonymous: true dispensa autenticação nessa rota especificamente. Sem spec.auth declarado no
documento, toda rota já é implicitamente anônima; o campo só passa a importar quando você adiciona
autenticação (veja Autenticação e autorização).
Para onde ir daqui
- Conceitos fundamentais — como o pipeline executa e a anatomia completa do documento YAML.
- Validação e mapeamento — o próximo passo natural: receber e validar dados de verdade.
- Um exemplo grande, real, rodando das duas formas acima:
samples/03-inventory-ordersno repositório do Pipevine — o mesmo YAML exercitando auth, persistência, transação e controle de fluxo de uma vez.