Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 258 additions & 0 deletions .github/workflows/prod-release-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
name: Release Pipeline

on:
workflow_dispatch:
inputs:
bump_type:
description: 'Version bump type'
required: true
default: 'patch'
type: choice
options:
- major
- minor
- patch
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
new_tag: ${{ steps.next_version.outputs.new_tag }}
steps:
- name: Checkout Repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # Fetch all history for changelog generation

- name: Get Latest Tag
id: get_latest_tag
run: |
# Get the latest tag, or use v0.0.0 if no tags exist
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "Latest tag: $LATEST_TAG"

- name: Calculate Next Version
id: next_version
run: |
LATEST_TAG="${{ steps.get_latest_tag.outputs.latest_tag }}"
# Remove 'v' prefix for calculation
VERSION=${LATEST_TAG#v}

# Split version into components
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"

# Bump version based on input
case "${{ github.event.inputs.bump_type }}" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
esac

NEW_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
echo "new_tag=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "New version: $NEW_VERSION"

- name: Generate Changelog
id: changelog
run: |
LATEST_TAG="${{ steps.get_latest_tag.outputs.latest_tag }}"
NEW_TAG="${{ steps.next_version.outputs.new_tag }}"

echo "# Release $NEW_TAG" > RELEASE_CHANGELOG.md
echo "" >> RELEASE_CHANGELOG.md
echo "## Changes since $LATEST_TAG" >> RELEASE_CHANGELOG.md
echo "" >> RELEASE_CHANGELOG.md

# Generate changelog from commits
if [ "$LATEST_TAG" = "v0.0.0" ]; then
# First release - include all commits
git log --pretty=format:"- %s (%h)" >> RELEASE_CHANGELOG.md
else
# Get commits since last tag
git log ${LATEST_TAG}..HEAD --pretty=format:"- %s (%h)" >> RELEASE_CHANGELOG.md
fi

echo "" >> RELEASE_CHANGELOG.md
echo "" >> RELEASE_CHANGELOG.md
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${LATEST_TAG}...${NEW_TAG}" >> RELEASE_CHANGELOG.md

cat RELEASE_CHANGELOG.md

- name: Create Tag
id: create_tag
uses: rickstaa/action-create-tag@v1
with:
tag: ${{ steps.next_version.outputs.new_tag }}
message: "Release ${{ steps.next_version.outputs.new_tag }}"
force_push_tag: false
github_token: ${{ secrets.GITHUB_TOKEN }}

- name: Create Release Archive
id: create_archive
run: |
NEW_TAG="${{ steps.next_version.outputs.new_tag }}"
ARCHIVE_NAME="vteam-${NEW_TAG}.tar.gz"

# Create archive of entire repository at this tag
git archive --format=tar.gz --prefix=vteam-${NEW_TAG}/ HEAD > $ARCHIVE_NAME

echo "archive_name=$ARCHIVE_NAME" >> $GITHUB_OUTPUT

- name: Create Release
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.next_version.outputs.new_tag }}
name: "Release ${{ steps.next_version.outputs.new_tag }}"
body_path: RELEASE_CHANGELOG.md
draft: false
prerelease: false
files: |
${{ steps.create_archive.outputs.archive_name }}
RELEASE_CHANGELOG.md

build-and-push:
runs-on: ubuntu-latest
needs: release
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
strategy:
matrix:
component:
- name: frontend
context: ./components/frontend
image: quay.io/ambient_code/vteam_frontend
dockerfile: ./components/frontend/Dockerfile
- name: backend
context: ./components/backend
image: quay.io/ambient_code/vteam_backend
dockerfile: ./components/backend/Dockerfile
- name: operator
context: ./components/operator
image: quay.io/ambient_code/vteam_operator
dockerfile: ./components/operator/Dockerfile
- name: claude-code-runner
context: ./components/runners
image: quay.io/ambient_code/vteam_claude_runner
dockerfile: ./components/runners/claude-code-runner/Dockerfile
steps:
- name: Checkout code from the tag generated above
uses: actions/checkout@v5
with:
ref: ${{ needs.release.outputs.new_tag }}
fetch-depth: 0


- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64

- name: Log in to Quay.io
uses: docker/login-action@v3
with:
registry: quay.io
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_PASSWORD }}

- name: Log in to Red Hat Container Registry
uses: docker/login-action@v3
with:
registry: registry.redhat.io
username: ${{ secrets.REDHAT_USERNAME }}
password: ${{ secrets.REDHAT_PASSWORD }}

- name: Build and push ${{ matrix.component.name }} image only for merge into main
uses: docker/build-push-action@v6
with:
context: ${{ matrix.component.context }}
file: ${{ matrix.component.dockerfile }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ matrix.component.image }}:${{ needs.release.outputs.new_tag }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Build ${{ matrix.component.name }} image for pull requests but don't push
uses: docker/build-push-action@v6
with:
context: ${{ matrix.component.context }}
file: ${{ matrix.component.dockerfile }}
platforms: linux/amd64,linux/arm64
push: false
tags: |
${{ matrix.component.image }}:${{ needs.release.outputs.new_tag }}
cache-from: type=gha
cache-to: type=gha,mode=max


deploy-to-openshift:
runs-on: ubuntu-latest
needs: [release, build-and-push]
strategy:
matrix:
component:
- name: frontend
context: ./components/frontend
image: quay.io/ambient_code/vteam_frontend
dockerfile: ./components/frontend/Dockerfile
- name: backend
context: ./components/backend
image: quay.io/ambient_code/vteam_backend
dockerfile: ./components/backend/Dockerfile
- name: operator
context: ./components/operator
image: quay.io/ambient_code/vteam_operator
dockerfile: ./components/operator/Dockerfile
- name: claude-code-runner
context: ./components/runners
image: quay.io/ambient_code/vteam_claude_runner
dockerfile: ./components/runners/claude-code-runner/Dockerfile
steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Install oc
uses: redhat-actions/oc-installer@v1
with:
oc_version: 'latest'

- name: Log in to OpenShift Cluster
run: |
oc login ${{ secrets.PROD_OPENSHIFT_SERVER }} --token=${{ secrets.PROD_OPENSHIFT_TOKEN }} --insecure-skip-tls-verify

- name: Deploy updated components to OpenShift
run: |
oc apply -k components/manifests

- name: Update frontend if changed
run: |
oc patch deployment frontend -n ambient-code --patch "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"vteam-frontend\",\"image\":\"quay.io/ambient_code/vteam_frontend:${{ needs.release.outputs.new_tag }}\"}]}}}}"

- name: Update backend if changed
run: |
oc patch deployment backend-api -n ambient-code --patch "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"vteam-backend\",\"image\":\"quay.io/ambient_code/vteam_backend:${{ needs.release.outputs.new_tag }}\"}]}}}}"

- name: Update operator if changed
run: |
oc patch deployment agentic-operator -n ambient-code --patch "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"vteam-operator\",\"image\":\"quay.io/ambient_code/vteam_operator:${{ needs.release.outputs.new_tag }}\"}]}}}}"

- name: force restart of pods to pick up changes
run: oc delete po --all -n ambient-code
Loading