Expand release workflow manifest gen #14
Workflow file for this run
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 Platform | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write # create release, upload assets | |
| packages: write # push images to GHCR | |
| env: | |
| REGISTRY: ghcr.io/livepeer-frameworks | |
| jobs: | |
| build-images: | |
| name: Build & Push Images | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| service: | |
| - { name: bridge, context: api_gateway, dockerfile: api_gateway/Dockerfile } | |
| - { name: quartermaster, context: api_tenants, dockerfile: api_tenants/Dockerfile } | |
| - { name: commodore, context: api_control, dockerfile: api_control/Dockerfile } | |
| - { name: purser, context: api_billing, dockerfile: api_billing/Dockerfile } | |
| - { name: foghorn, context: api_balancing, dockerfile: api_balancing/Dockerfile } | |
| - { name: decklog, context: api_firehose, dockerfile: api_firehose/Dockerfile } | |
| - { name: periscope-ingest, context: api_analytics_ingest, dockerfile: api_analytics_ingest/Dockerfile } | |
| - { name: periscope-query, context: api_analytics_query, dockerfile: api_analytics_query/Dockerfile } | |
| - { name: signalman, context: api_realtime, dockerfile: api_realtime/Dockerfile } | |
| - { name: helmsman, context: api_sidecar, dockerfile: api_sidecar/Dockerfile } | |
| - { name: forms-api, context: api_forms, dockerfile: api_forms/Dockerfile } | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Log in to DockerHub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Read service component version (optional) | |
| id: svcver | |
| run: | | |
| VERSION_FILE="${{ matrix.service.context }}/VERSION" | |
| PACKAGE_JSON="${{ matrix.service.context }}/package.json" | |
| if [[ -f "$VERSION_FILE" ]]; then | |
| echo "version=$(tr -d '\n' < "$VERSION_FILE")" >> "$GITHUB_OUTPUT" | |
| elif [[ -f "$PACKAGE_JSON" ]]; then | |
| echo "version=$(jq -r .version "$PACKAGE_JSON")" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "version=0.0.0" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Build & push ${{ matrix.service.name }} | |
| id: build | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ${{ matrix.service.dockerfile }} | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| provenance: true | |
| sbom: true | |
| build-args: | | |
| VERSION=${{ github.ref_name }} | |
| GIT_COMMIT=${{ github.sha }} | |
| BUILD_DATE=${{ github.event.repository.updated_at }} | |
| COMPONENT_NAME=${{ matrix.service.name }} | |
| COMPONENT_VERSION=${{ steps.svcver.outputs.version }} | |
| tags: | | |
| ${{ env.REGISTRY }}/frameworks-${{ matrix.service.name }}:${{ github.ref_name }} | |
| livepeerframeworks/frameworks-${{ matrix.service.name }}:${{ github.ref_name }} | |
| cache-from: type=gha,scope=${{ matrix.service.name }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.service.name }} | |
| - name: Write digest artifact | |
| run: | | |
| mkdir -p dist | |
| cat > dist/image-${{ matrix.service.name }}.json <<JSON | |
| { | |
| "name": "${{ matrix.service.name }}", | |
| "image": "docker.io/livepeerframeworks/frameworks-${{ matrix.service.name }}:${{ github.ref_name }}", | |
| "digest": "${{ steps.build.outputs.digest }}", | |
| "service_version": "${{ steps.svcver.outputs.version }}", | |
| "git_commit": "${{ github.sha }}" | |
| } | |
| JSON | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: image-digest-${{ matrix.service.name }} | |
| path: dist/image-${{ matrix.service.name }}.json | |
| build-webapps: | |
| name: Build Web Applications | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| webapp: | |
| - { name: webapp, context: website_application, env_prefix: VITE, build_dir: build } | |
| - { name: website, context: website_marketing, env_prefix: VITE, build_dir: dist } | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v2 | |
| with: | |
| version: 9 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'pnpm' | |
| cache-dependency-path: 'pnpm-lock.yaml' | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build player package | |
| run: | | |
| cd npm_player | |
| pnpm run build | |
| - name: Build application | |
| env: | |
| # webapp (website_application) variables | |
| VITE_AUTH_URL: ${{ secrets.VITE_AUTH_URL }} | |
| VITE_GRAPHQL_HTTP_URL: ${{ secrets.VITE_GRAPHQL_HTTP_URL }} | |
| VITE_GRAPHQL_WS_URL: ${{ secrets.VITE_GRAPHQL_WS_URL }} | |
| VITE_RTMP_DOMAIN: ${{ secrets.VITE_RTMP_DOMAIN }} | |
| VITE_HTTP_DOMAIN: ${{ secrets.VITE_HTTP_DOMAIN }} | |
| VITE_CDN_DOMAIN: ${{ secrets.VITE_CDN_DOMAIN }} | |
| VITE_RTMP_PATH: ${{ secrets.VITE_RTMP_PATH }} | |
| VITE_HLS_PATH: ${{ secrets.VITE_HLS_PATH }} | |
| VITE_WEBRTC_PATH: ${{ secrets.VITE_WEBRTC_PATH }} | |
| VITE_EMBED_PATH: ${{ secrets.VITE_EMBED_PATH }} | |
| VITE_MARKETING_SITE_URL: ${{ secrets.VITE_MARKETING_SITE_URL }} | |
| VITE_TURNSTILE_AUTH_SITE_KEY: ${{ secrets.VITE_TURNSTILE_AUTH_SITE_KEY }} | |
| # website (website_marketing) variables | |
| VITE_APP_URL: ${{ secrets.VITE_APP_URL }} | |
| VITE_CONTACT_API_URL: ${{ secrets.VITE_CONTACT_API_URL }} | |
| VITE_GATEWAY_URL: ${{ secrets.VITE_GATEWAY_URL }} | |
| VITE_GITHUB_URL: ${{ secrets.VITE_GITHUB_URL }} | |
| VITE_LIVEPEER_URL: ${{ secrets.VITE_LIVEPEER_URL }} | |
| VITE_LIVEPEER_EXPLORER_URL: ${{ secrets.VITE_LIVEPEER_EXPLORER_URL }} | |
| VITE_CONTACT_EMAIL: ${{ secrets.VITE_CONTACT_EMAIL }} | |
| VITE_FORUM_URL: ${{ secrets.VITE_FORUM_URL }} | |
| VITE_DISCORD_URL: ${{ secrets.VITE_DISCORD_URL }} | |
| VITE_DEMO_STREAM_NAME: ${{ secrets.VITE_DEMO_STREAM_NAME }} | |
| VITE_COMPANY_NAME: ${{ secrets.VITE_COMPANY_NAME }} | |
| VITE_DOMAIN: ${{ secrets.VITE_DOMAIN }} | |
| VITE_TURNSTILE_FORMS_SITE_KEY: ${{ secrets.VITE_TURNSTILE_FORMS_SITE_KEY }} | |
| run: | | |
| cd ${{ matrix.webapp.context }} | |
| pnpm run build | |
| - name: Create static bundle | |
| run: | | |
| cd ${{ matrix.webapp.context }} | |
| tar czf ../${{ matrix.webapp.name }}-build.tar.gz ${{ matrix.webapp.build_dir }}/ | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Log in to DockerHub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Build and push Docker image | |
| id: build | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ${{ matrix.webapp.context }}/Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| provenance: true | |
| sbom: true | |
| tags: | | |
| ${{ env.REGISTRY }}/frameworks-${{ matrix.webapp.name }}:${{ github.ref_name }} | |
| livepeerframeworks/frameworks-${{ matrix.webapp.name }}:${{ github.ref_name }} | |
| cache-from: type=gha,scope=${{ matrix.webapp.name }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.webapp.name }} | |
| - name: Write digest artifact | |
| run: | | |
| mkdir -p dist | |
| cat > dist/image-${{ matrix.webapp.name }}.json <<JSON | |
| { | |
| "name": "${{ matrix.webapp.name }}", | |
| "image": "docker.io/livepeerframeworks/frameworks-${{ matrix.webapp.name }}:${{ github.ref_name }}", | |
| "digest": "${{ steps.build.outputs.digest }}", | |
| "git_commit": "${{ github.sha }}" | |
| } | |
| JSON | |
| - name: Upload digest artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: image-digest-${{ matrix.webapp.name }} | |
| path: dist/image-${{ matrix.webapp.name }}.json | |
| - name: Upload static bundle artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.webapp.name }}-bundle | |
| path: ${{ matrix.webapp.name }}-build.tar.gz | |
| build-cli: | |
| name: Build CLI binaries | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| include: | |
| - goos: linux | |
| goarch: amd64 | |
| ext: "" | |
| - goos: linux | |
| goarch: arm64 | |
| ext: "" | |
| - goos: darwin | |
| goarch: amd64 | |
| ext: "" | |
| - goos: darwin | |
| goarch: arm64 | |
| ext: "" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Sanitize platform tag to component version | |
| id: compver | |
| run: | | |
| ver="${GITHUB_REF_NAME#v}" | |
| echo "value=${ver}" >> "$GITHUB_OUTPUT" | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| cache-dependency-path: cli/go.sum | |
| - name: Build CLI ${{ matrix.goos }}/${{ matrix.goarch }} | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| CGO_ENABLED: 0 | |
| run: | | |
| set -euo pipefail | |
| cd cli | |
| out="frameworks-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.ext }}" | |
| go build -ldflags "-X frameworks/pkg/version.Version=${{ github.ref_name }} -X frameworks/pkg/version.GitCommit=${{ github.sha }} -X frameworks/pkg/version.BuildDate=$(date -u '+%Y-%m-%dT%H:%M:%SZ') -X frameworks/pkg/version.ComponentName=cli -X frameworks/pkg/version.ComponentVersion=${{ steps.compver.outputs.value }}" -o "$out" . | |
| cd .. | |
| mkdir -p dist/cli | |
| mv "cli/$out" "dist/cli/$out" | |
| - name: Upload CLI artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: cli-${{ matrix.goos }}-${{ matrix.goarch }} | |
| path: dist/cli/* | |
| build-service-binaries: | |
| name: Build Service Binaries | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| service: | |
| - { name: bridge, context: api_gateway, cmd_path: ./cmd/bridge } | |
| - { name: quartermaster, context: api_tenants, cmd_path: ./cmd/quartermaster } | |
| - { name: commodore, context: api_control, cmd_path: ./cmd/commodore } | |
| - { name: purser, context: api_billing, cmd_path: ./cmd/purser } | |
| - { name: foghorn, context: api_balancing, cmd_path: ./cmd/foghorn } | |
| - { name: decklog, context: api_firehose, cmd_path: cmd/decklog/main.go } | |
| - { name: periscope-ingest, context: api_analytics_ingest, cmd_path: ./cmd/periscope } | |
| - { name: periscope-query, context: api_analytics_query, cmd_path: ./cmd/periscope } | |
| - { name: signalman, context: api_realtime, cmd_path: ./cmd/signalman } | |
| - { name: helmsman, context: api_sidecar, cmd_path: ./cmd/helmsman } | |
| arch: | |
| - { goos: linux, goarch: amd64 } | |
| - { goos: linux, goarch: arm64 } | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| cache-dependency-path: ${{ matrix.service.context }}/go.sum | |
| - name: Read service version | |
| id: svcver | |
| run: | | |
| VERSION_FILE="${{ matrix.service.context }}/VERSION" | |
| if [[ -f "$VERSION_FILE" ]]; then | |
| echo "version=$(tr -d '\n' < "$VERSION_FILE")" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "version=0.0.0" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Build binary | |
| env: | |
| GOOS: ${{ matrix.arch.goos }} | |
| GOARCH: ${{ matrix.arch.goarch }} | |
| CGO_ENABLED: 0 | |
| run: | | |
| set -euo pipefail | |
| cd ${{ matrix.service.context }} | |
| BINARY_NAME="frameworks-${{ matrix.service.name }}-${{ matrix.arch.goos }}-${{ matrix.arch.goarch }}" | |
| OUTPUT="frameworks-${{ matrix.service.name }}-${{ github.ref_name }}-${{ matrix.arch.goos }}-${{ matrix.arch.goarch }}" | |
| go build -ldflags "\ | |
| -X frameworks/pkg/version.Version=${{ github.ref_name }} \ | |
| -X frameworks/pkg/version.GitCommit=${{ github.sha }} \ | |
| -X frameworks/pkg/version.BuildDate=$(date -u '+%Y-%m-%dT%H:%M:%SZ') \ | |
| -X frameworks/pkg/version.ComponentName=${{ matrix.service.name }} \ | |
| -X frameworks/pkg/version.ComponentVersion=${{ steps.svcver.outputs.version }} \ | |
| -s -w" \ | |
| -o "${BINARY_NAME}" \ | |
| ${{ matrix.service.cmd_path }} | |
| # Create output directory | |
| mkdir -p ../dist/binaries/${{ matrix.service.name }} | |
| # Package binary with platform version in filename | |
| tar czf "../dist/binaries/${{ matrix.service.name }}/${OUTPUT}.tar.gz" "${BINARY_NAME}" | |
| - name: Upload binary artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: binary-${{ matrix.service.name }}-${{ matrix.arch.goos }}-${{ matrix.arch.goarch }} | |
| path: dist/binaries/${{ matrix.service.name }}/*.tar.gz | |
| manifest: | |
| name: Generate & Publish Manifest | |
| needs: [build-images, build-webapps, build-cli, build-service-binaries] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download image digest artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: image-digest-* | |
| path: dist/digests | |
| merge-multiple: true | |
| - name: Fetch MistServer digest from DockerHub | |
| id: mistserver | |
| run: | | |
| set -euo pipefail | |
| # Get manifest digest from DockerHub | |
| DIGEST=$(curl -sI \ | |
| -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ | |
| "https://registry-1.docker.io/v2/livepeerframeworks/mistserver/manifests/latest" \ | |
| | grep -i docker-content-digest \ | |
| | awk '{print $2}' \ | |
| | tr -d '\r') | |
| if [[ -z "$DIGEST" ]]; then | |
| echo "WARNING: Could not fetch MistServer digest from DockerHub, using placeholder" | |
| DIGEST="sha256:TODO-fetch-failed" | |
| fi | |
| echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT" | |
| echo "Fetched MistServer digest: ${DIGEST}" | |
| - name: Generate manifest | |
| run: | | |
| set -euo pipefail | |
| # Header | |
| cat > dist/manifest.yaml <<YAML | |
| platform_version: ${{ github.ref_name }} | |
| git_commit: ${{ github.sha }} | |
| release_date: $(date -u '+%Y-%m-%dT%H:%M:%SZ') | |
| YAML | |
| # Services (microservices with service_version field) | |
| echo "services:" >> dist/manifest.yaml | |
| for f in dist/digests/*.json; do | |
| name=$(jq -r .name "$f") | |
| # Skip webapp/website - they go in interfaces section | |
| if [[ "$name" == "webapp" || "$name" == "website" ]]; then | |
| continue | |
| fi | |
| image=$(jq -r .image "$f") | |
| digest=$(jq -r .digest "$f") | |
| svcver=$(jq -r .service_version "$f") | |
| cat >> dist/manifest.yaml <<YAML | |
| - name: ${name} | |
| service_version: ${svcver} | |
| image: ${image} | |
| digest: ${digest} | |
| YAML | |
| done | |
| # Native Binaries (for bare-metal deployment) | |
| echo "" >> dist/manifest.yaml | |
| echo "native_binaries:" >> dist/manifest.yaml | |
| for f in dist/digests/*.json; do | |
| name=$(jq -r .name "$f") | |
| # Skip webapp/website - they don't have native binaries | |
| if [[ "$name" == "webapp" || "$name" == "website" ]]; then | |
| continue | |
| fi | |
| svcver=$(jq -r .service_version "$f") | |
| cat >> dist/manifest.yaml <<YAML | |
| - name: ${name} | |
| service_version: ${svcver} | |
| deployment_method: systemd | |
| artifacts: | |
| - arch: linux-amd64 | |
| file: frameworks-${name}-${{ github.ref_name }}-linux-amd64.tar.gz | |
| - arch: linux-arm64 | |
| file: frameworks-${name}-${{ github.ref_name }}-linux-arm64.tar.gz | |
| YAML | |
| done | |
| # Interfaces (webapp/website reference implementations) | |
| echo "" >> dist/manifest.yaml | |
| echo "interfaces:" >> dist/manifest.yaml | |
| for f in dist/digests/*.json; do | |
| name=$(jq -r .name "$f") | |
| # Only include webapp/website | |
| if [[ "$name" != "webapp" && "$name" != "website" ]]; then | |
| continue | |
| fi | |
| image=$(jq -r .image "$f") | |
| digest=$(jq -r .digest "$f") | |
| # Determine build dir and bundle name | |
| if [[ "$name" == "webapp" ]]; then | |
| bundle="webapp-build.tar.gz" | |
| else | |
| bundle="website-build.tar.gz" | |
| fi | |
| cat >> dist/manifest.yaml <<YAML | |
| - name: ${name} | |
| type: reference-implementation | |
| deployment_options: [docker, systemd] | |
| image: ${image} | |
| digest: ${digest} | |
| static_bundle: ${bundle} | |
| note: "White-label example - fork and customize for production deployments" | |
| YAML | |
| done | |
| # External Dependencies (MistServer from separate repo) | |
| echo "" >> dist/manifest.yaml | |
| cat >> dist/manifest.yaml <<YAML | |
| external_dependencies: | |
| - name: mistserver | |
| repository: github.com/Livepeer-FrameWorks/mistserver | |
| image: docker.io/livepeerframeworks/mistserver:latest | |
| digest: "${{ steps.mistserver.outputs.digest }}" | |
| compatibility_level: backwards-compatible | |
| required_by: [helmsman] | |
| deployment_options: [native-preferred, docker] | |
| note: "Built from separate fork - pinning optional due to backwards compatibility" | |
| YAML | |
| # Infrastructure Requirements (from config/infrastructure.yaml) | |
| echo "" >> dist/manifest.yaml | |
| cat config/infrastructure.yaml >> dist/manifest.yaml | |
| - name: Upload manifest artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-manifest | |
| path: dist/manifest.yaml | |
| - name: Download CLI artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: cli-* | |
| path: dist/cli | |
| merge-multiple: true | |
| - name: Download service binary artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: binary-* | |
| path: dist/binaries | |
| merge-multiple: true | |
| - name: Download webapp bundle | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: webapp-bundle | |
| path: dist/ | |
| - name: Download website bundle | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: website-bundle | |
| path: dist/ | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: ${{ github.ref_name }} | |
| generate_release_notes: true | |
| files: | | |
| dist/manifest.yaml | |
| dist/cli/* | |
| dist/binaries/*.tar.gz | |
| dist/webapp-build.tar.gz | |
| dist/website-build.tar.gz | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| update-env: | |
| name: Update GitOps Environment Repo | |
| needs: [manifest] | |
| runs-on: ubuntu-latest | |
| env: | |
| ENV_REPO: Livepeer-FrameWorks/gitops | |
| RELEASE_BRANCH: release/${{ github.ref_name }} | |
| steps: | |
| - name: Checkout env repo | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ env.ENV_REPO }} | |
| token: ${{ secrets.GITOPS_REPO_TOKEN }} | |
| path: env-repo | |
| - name: Download manifest artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-manifest | |
| path: dist | |
| - name: Commit and push manifest to env repo | |
| run: | | |
| set -euo pipefail | |
| cd env-repo | |
| # Create release manifest | |
| mkdir -p releases | |
| cp ../dist/manifest.yaml releases/${{ github.ref_name }}.yaml | |
| # Update channel pointer | |
| channel="stable" | |
| if [[ "${{ github.ref_name }}" == *"-rc."* ]]; then channel="rc"; fi | |
| mkdir -p channels | |
| cat > channels/${channel}.yaml <<YAML | |
| platform_version: ${{ github.ref_name }} | |
| manifest: releases/${{ github.ref_name }}.yaml | |
| updated_at: $(date -u '+%Y-%m-%dT%H:%M:%SZ') | |
| YAML | |
| # Commit and push | |
| git config user.name "github-actions" | |
| git config user.email "[email protected]" | |
| # Fetch branch if it exists | |
| git fetch origin "${RELEASE_BRANCH}" || true | |
| # Create or reset to new content | |
| git checkout -B "${RELEASE_BRANCH}" | |
| git add releases/${{ github.ref_name }}.yaml channels/${channel}.yaml | |
| git commit -m "Release manifest for ${{ github.ref_name }}" | |
| git push --force origin "${RELEASE_BRANCH}" | |
| - name: Create or update PR to env repo | |
| env: | |
| GH_TOKEN: ${{ secrets.GITOPS_REPO_TOKEN }} | |
| run: | | |
| cd env-repo | |
| # Check if PR already exists | |
| PR_NUMBER=$(gh pr list \ | |
| --repo "${{ env.ENV_REPO }}" \ | |
| --head "${RELEASE_BRANCH}" \ | |
| --base main \ | |
| --json number \ | |
| --jq '.[0].number' 2>/dev/null || echo "") | |
| if [[ -n "$PR_NUMBER" ]]; then | |
| echo "PR #${PR_NUMBER} already exists and was updated via branch push" | |
| echo "https://github.com/${{ env.ENV_REPO }}/pull/${PR_NUMBER}" | |
| else | |
| gh pr create \ | |
| --repo "${{ env.ENV_REPO }}" \ | |
| --base main \ | |
| --head "${RELEASE_BRANCH}" \ | |
| --title "Release ${{ github.ref_name }} manifest" \ | |
| --body "This PR adds the release manifest for ${{ github.ref_name }}. | |
| It maps each service to image@digest and includes component versions. | |
| **Platform Version:** \`${{ github.ref_name }}\` | |
| **Git Commit:** \`${{ github.sha }}\` | |
| **Release Date:** \`$(date -u '+%Y-%m-%dT%H:%M:%SZ')\`" | |
| fi |