Build, Release & CI/CD
release-please versioning, GoReleaser for Grape, Docker builds for Tendril, and GitHub Actions workflows.
Build, Release & CI/CD
Grape (CLI) and Tendril (agent) are versioned and released independently using release-please with conventional commits. Each component has its own release workflow, tag format, and distribution channel.
release-please Configuration
The monorepo uses release-please with separate-pull-requests: true, meaning each component gets its own release PR.
// release-please-config.json
{
"separate-pull-requests": true,
"packages": {
"apps/grape": {
"release-type": "simple",
"component": "grape",
"include-component-in-tag": true,
"changelog-path": "CHANGELOG.md"
},
"apps/tendril": {
"release-type": "simple",
"component": "tendril",
"include-component-in-tag": true,
"changelog-path": "CHANGELOG.md"
}
}
}How it works:
- Developers write conventional commits:
feat(grape): add vine get command,fix(tendril): handle nil credential - On push to main, release-please analyzes commits since the last release
- It creates (or updates) a release PR per component with:
- Version bump (major/minor/patch based on commit type)
- Auto-generated CHANGELOG.md entries
- When merged, release-please creates a git tag (
grape-v0.1.8ortendril-v0.1.0) - The tag triggers the component's release workflow
Grape Release Pipeline
Trigger: Push to tag matching grape-v*
Workflow: .github/workflows/release-grape.yml
Tag push (grape-v0.1.8)
└── Checkout + Go setup
└── GoReleaser
├── Build: darwin/amd64, darwin/arm64, linux/amd64, linux/arm64
├── Archive: tar.gz per platform
├── GitHub Release: upload archives + checksums
└── Homebrew: update formula in bobikenobi12/bb-thesis-2026 tapGoReleaser config (apps/grape/.goreleaser.yml):
- Builds 4 binaries (2 OS x 2 arch)
- Creates GitHub Release with download links
- Updates Homebrew tap formula automatically
Distribution channels:
brew install bobikenobi12/bb-thesis-2026/grape(macOS/Linux via Homebrew)- Direct binary download from GitHub Releases
Tendril Release Pipeline
Trigger: Push to tag matching tendril-v*
Workflow: .github/workflows/release-tendril.yml
Tag push (tendril-v0.1.0)
└── Checkout
└── Stage templates
├── infra/templates/vine/aws → apps/tendril/vine-templates/aws
├── infra/templates/vine/gcp → apps/tendril/vine-templates/gcp
├── infra/templates/vine/azure → apps/tendril/vine-templates/azure
├── infra/templates/tendril → apps/tendril/tendril-templates
└── infra/templates/argocd → apps/tendril/argocd-templates
└── Docker buildx (ARM64)
├── Push to AWS ECR (eu-west-1)
└── Push to GitHub Container Registry (ghcr.io)
└── Publish release metadata
└── POST /api/releases/worker { version, release_notes }
└── Force new ECS Fargate deployment
└── aws ecs update-service --force-new-deploymentKey details:
- Template staging: Infrastructure templates are copied into the Docker build context so the final image contains all Terraform modules for AWS, GCP, and Azure
- ARM64 only: Tendril runs on Graviton (ARM) Fargate tasks for cost efficiency
- Dual registry: ECR for production Fargate deployment, GHCR for public access
- API publish: Trellis is notified of new releases and can display version info in the UI
- Rolling deployment:
--force-new-deploymenttriggers ECS to launch new tasks with the updated image
Tendril Dev Deployment
Trigger: Manual (workflow_dispatch)
Workflow: .github/workflows/deploy-tendril.yml
For development/hotfix deployments without a version tag. Builds and deploys using the git SHA as the image tag instead of a semver version. Same Docker build and ECS deployment steps as the release workflow.
release-please Automation
Workflow: .github/workflows/release-please.yml
Trigger: Push to default branch
Runs googleapis/release-please-action which:
- Reads
release-please-config.jsonand.release-please-manifest.json - Analyzes conventional commits since the last release per component
- Creates/updates release PRs with changelogs
- On PR merge, creates git tags that trigger release workflows
Manifest (.release-please-manifest.json) tracks current versions:
{
"apps/grape": "0.1.7",
"apps/tendril": "0.0.0"
}Version Tracking in the Platform
When a Tendril release is published, the Trellis API receives the version and release notes via POST /api/releases/worker. This creates a worker_releases record. Registered Tendrils reference their release_id so the platform can:
- Display current version per Tendril in the UI
- Show release notes and changelogs
- Detect outdated Tendrils