Vintner

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 Pipeline

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:

  1. Developers write conventional commits: feat(grape): add vine get command, fix(tendril): handle nil credential
  2. On push to main, release-please analyzes commits since the last release
  3. It creates (or updates) a release PR per component with:
    • Version bump (major/minor/patch based on commit type)
    • Auto-generated CHANGELOG.md entries
  4. When merged, release-please creates a git tag (grape-v0.1.8 or tendril-v0.1.0)
  5. 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 tap

GoReleaser 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-deployment

Key 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-deployment triggers 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:

  1. Reads release-please-config.json and .release-please-manifest.json
  2. Analyzes conventional commits since the last release per component
  3. Creates/updates release PRs with changelogs
  4. 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

On this page