Release Pipeline #9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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: | | |
| # List all existing tags for debugging | |
| echo "All existing tags:" | |
| git tag --list 'v*.*.*' --sort=-version:refname | |
| # Get the latest tag using version sort, or use v0.0.0 if no tags exist | |
| LATEST_TAG=$(git tag --list 'v*.*.*' --sort=-version:refname | head -n 1) | |
| if [ -z "$LATEST_TAG" ]; then | |
| exit 1 | |
| fi | |
| 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@v2 | |
| 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 | |
| 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 | |
| deploy-to-openshift: | |
| runs-on: ubuntu-latest | |
| needs: [release, build-and-push] | |
| 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: Delete deployments in ambient-code namespace to force re-deploy | |
| run: | | |
| oc delete deployment --all -n ambient-code | |
| - 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\":\"frontend\",\"image\":\"quay.io/ambient_code/vteam_frontend:${{ needs.release.outputs.new_tag }}\",\"env\":[{\"name\":\"BACKEND_URL\",\"value\":\"http://backend-service:8080/api\"},{\"name\":\"NODE_ENV\",\"value\":\"production\"},{\"name\":\"GITHUB_APP_SLUG\",\"value\":\"ambient-code\"},{\"name\":\"VTEAM_VERSION\",\"value\":\"${{ 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\":\"backend-api\",\"image\":\"quay.io/ambient_code/vteam_backend:${{ needs.release.outputs.new_tag }}\"}]}}}}" | |
| - name: Update operator image and environment variables | |
| run: | | |
| oc patch deployment agentic-operator -n ambient-code --patch "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"agentic-operator\",\"image\":\"quay.io/ambient_code/vteam_operator:${{ needs.release.outputs.new_tag }}\"}]}}}}" | |
| oc patch deployment agentic-operator -n ambient-code --type=json -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/env", "value": [{"name":"NAMESPACE","valueFrom":{"fieldRef":{"fieldPath":"metadata.namespace"}}},{"name":"BACKEND_NAMESPACE","valueFrom":{"fieldRef":{"fieldPath":"metadata.namespace"}}},{"name":"BACKEND_API_URL","value":"http://backend-service:8080/api"},{"name":"AMBIENT_CODE_RUNNER_IMAGE","value":"quay.io/ambient_code/vteam_claude_runner:${{ needs.release.outputs.new_tag }}"},{"name":"CONTENT_SERVICE_IMAGE","value":"quay.io/ambient_code/vteam_backend:${{ needs.release.outputs.new_tag }}"},{"name":"IMAGE_PULL_POLICY","value":"Always"}]}]' |