name: Release Pipeline # Triggers automatically on push to main when any version file changes on: push: branches: ["main"] workflow_dispatch: inputs: skip_tests: description: 'Skip all tests and jump directly to release (admin only)' required: false type: boolean default: false # Prevent concurrent runs concurrency: group: release-pipeline cancel-in-progress: false permissions: contents: read jobs: # Check if pipeline should be skipped based on first line of commit message check-skip: runs-on: ubuntu-latest outputs: should-skip: ${{ steps.check.outputs.should-skip }} skip-tests: ${{ steps.skip_tests.outputs.skip-tests }} steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: >+ api.github.com:443 - name: Check if pipeline should be skipped id: check env: COMMIT_MESSAGE: ${{ github.event.head_commit.message }} run: | FIRST_LINE=$(echo "$COMMIT_MESSAGE" | head -n 1) if [[ "$FIRST_LINE" == *"--skip-ci"* ]]; then echo "should-skip=true" >> $GITHUB_OUTPUT else echo "should-skip=false" >> $GITHUB_OUTPUT fi - name: Validate admin permission for skip_tests id: skip_tests env: GH_TOKEN: ${{ secrets.GH_TOKEN }} run: | if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.skip_tests }}" == "true" ]]; then PERMISSION=$(gh api repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission --jq '.permission') if [[ "$PERMISSION" != "admin" ]]; then echo "::error::Only repository admins can use skip_tests=true. ${{ github.actor }} has permission: $PERMISSION" exit 1 fi echo "Admin verified: ${{ github.actor }} ($PERMISSION)" echo "skip-tests=true" >> $GITHUB_OUTPUT else echo "skip-tests=false" >> $GITHUB_OUTPUT fi # Detect what needs to be released detect-changes: needs: [check-skip] runs-on: ubuntu-latest # Skip if first line of commit message contains --skip-ci if: needs.check-skip.outputs.should-skip != 'true' outputs: core-needs-release: ${{ steps.detect.outputs.core-needs-release }} framework-needs-release: ${{ steps.detect.outputs.framework-needs-release }} plugins-need-release: ${{ steps.detect.outputs.plugins-need-release }} bifrost-http-needs-release: ${{ steps.detect.outputs.bifrost-http-needs-release }} docker-needs-release: ${{ steps.detect.outputs.docker-needs-release }} changed-plugins: ${{ steps.detect.outputs.changed-plugins }} core-version: ${{ steps.detect.outputs.core-version }} framework-version: ${{ steps.detect.outputs.framework-version }} transport-version: ${{ steps.detect.outputs.transport-version }} steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > _http._tcp.azure.archive.ubuntu.com:443 _https._tcp.esm.ubuntu.com:443 _https._tcp.motd.ubuntu.com:443 _https._tcp.packages.microsoft.com:443 api.github.com:443 azure.archive.ubuntu.com:80 dl.google.com:443 esm.ubuntu.com:443 github.com:443 packages.microsoft.com:443 proxy.golang.org:443 registry.hub.docker.com:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Install jq run: | sudo apt-get update sudo apt-get install -y jq - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Detect what needs release id: detect run: ./.github/workflows/scripts/detect-all-changes.sh "auto" - name: Validate Helm templates run: | chmod +x .github/workflows/scripts/validate-helm-templates.sh .github/workflows/scripts/validate-helm-templates.sh - name: Validate Helm config fields run: | chmod +x .github/workflows/scripts/validate-helm-config-fields.sh .github/workflows/scripts/validate-helm-config-fields.sh - name: Validate Go ↔ config.schema.json ↔ helm-chart sync (schemasync) run: | chmod +x .github/workflows/scripts/validate-schema-sync.sh .github/workflows/scripts/validate-schema-sync.sh # Run all tests in parallel before any releases test-core: needs: [check-skip, detect-changes] if: needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.core-needs-release == 'true' runs-on: ubuntu-latest permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > api.anthropic.com:443 api.cerebras.ai:443 api.cohere.ai:443 api.elevenlabs.io:443 api.fireworks.ai:443 api.github.com:443 api.groq.com:443 api.mistral.ai:443 api.openai.com:443 api.parasail.io:443 api.perplexity.ai:443 bedrock-runtime.us-east-1.amazonaws.com:443 bedrock.us-east-1.amazonaws.com:443 bifrost-batch-api-file-upload-testing.s3.us-east-1.amazonaws.com:443 fal.media:443 generativelanguage.googleapis.com:443 github.com:443 huggingface.co:443 login.microsoftonline.com:443 maxim-o1.openai.azure.com:443 nodejs.org:443 openrouter.ai:443 proxy.golang.org:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 router.huggingface.co:443 storage.googleapis.com:443 sum.golang.org:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Run core tests env: MAXIM_API_KEY: ${{ secrets.MAXIM_API_KEY }} MAXIM_LOGGER_ID: ${{ secrets.MAXIM_LOG_REPO_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }} AWS_ARN: ${{ secrets.AWS_ARN }} BEDROCK_API_KEY: ${{ secrets.BEDROCK_API_KEY }} AZURE_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }} AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} PARASAIL_API_KEY: ${{ secrets.PARASAIL_API_KEY }} ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }} SGL_API_KEY: ${{ secrets.SGL_API_KEY }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} VERTEX_CREDENTIALS: ${{ secrets.VERTEX_CREDENTIALS }} VERTEX_PROJECT_ID: ${{ secrets.VERTEX_PROJECT_ID }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} HUGGING_FACE_API_KEY: ${{ secrets.HUGGING_FACE_API_KEY }} AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} AWS_BEDROCK_ROLE_ARN: ${{ secrets.AWS_BEDROCK_ROLE_ARN }} BIFROST_ENCRYPTION_KEY: ${{ secrets.BIFROST_ENCRYPTION_KEY }} run: ./.github/workflows/scripts/test-core.sh # Approval gate for flaky test-core failures # If test-core fails (often due to flaky provider API calls), this job waits for manual approval # to continue the release pipeline without requiring a full re-run approve-flaky-test-core: needs: [check-skip, detect-changes, test-core] if: | always() && needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.core-needs-release == 'true' && needs.test-core.result == 'failure' runs-on: ubuntu-latest environment: name: flaky-test-override url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} outputs: approved: ${{ steps.approve.outputs.approved }} steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: >+ - name: Display failed test info run: | echo "::warning::test-core failed. Review the logs to determine if this is a flaky test." echo "If this is a known flaky test (e.g., provider API timeout), approve to continue." echo "If this is a real failure, reject and fix the issue." - name: Mark as approved id: approve run: echo "approved=true" >> $GITHUB_OUTPUT test-framework: needs: [check-skip, detect-changes] if: needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.framework-needs-release == 'true' runs-on: ubuntu-latest permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > _grpc_config.cluster.qdrant.io:443 _grpc_config.localhost:443 api.github.com:443 auth.docker.io:443 cluster.qdrant.io:443 cluster.weaviate.network:443 codecov.io:443 dl-cdn.alpinelinux.org:443 ghcr.io:443 github.com:443 pkg-containers.githubusercontent.com:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 telemetry.qdrant.io:443 uploader.codecov.io:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Docker Compose run: | docker --version if ! docker compose version >/dev/null 2>&1; then echo "Installing Docker Compose..." sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version else echo "Docker Compose plugin is available" docker compose version fi - name: Run framework tests env: MAXIM_API_KEY: ${{ secrets.MAXIM_API_KEY }} MAXIM_LOGGER_ID: ${{ secrets.MAXIM_LOG_REPO_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }} AWS_ARN: ${{ secrets.AWS_ARN }} BEDROCK_API_KEY: ${{ secrets.BEDROCK_API_KEY }} AZURE_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }} AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} PARASAIL_API_KEY: ${{ secrets.PARASAIL_API_KEY }} ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }} SGL_API_KEY: ${{ secrets.SGL_API_KEY }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} VERTEX_CREDENTIALS: ${{ secrets.VERTEX_CREDENTIALS }} VERTEX_PROJECT_ID: ${{ secrets.VERTEX_PROJECT_ID }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} HUGGING_FACE_API_KEY: ${{ secrets.HUGGING_FACE_API_KEY }} BIFROST_ENCRYPTION_KEY: ${{ secrets.BIFROST_ENCRYPTION_KEY }} run: ./.github/workflows/scripts/test-framework.sh test-plugins: needs: [check-skip, detect-changes] if: needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.plugins-need-release == 'true' runs-on: ubuntu-latest permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > _grpc_config.localhost:443 _http._tcp.azure.archive.ubuntu.com:443 _https._tcp.esm.ubuntu.com:443 _https._tcp.motd.ubuntu.com:443 _https._tcp.packages.microsoft.com:443 api.github.com:443 api.openai.com:443 auth.docker.io:443 azure.archive.ubuntu.com:80 codecov.io:443 dl-cdn.alpinelinux.org:443 esm.ubuntu.com:443 getbifrost.ai:443 ghcr.io:443 github.com:443 packages.microsoft.com:443 pkg-containers.githubusercontent.com:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 telemetry.qdrant.io:443 uploader.codecov.io:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Install jq run: | sudo apt-get update sudo apt-get install -y jq - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Docker Compose run: | docker --version if ! docker compose version >/dev/null 2>&1; then echo "Installing Docker Compose..." sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version else echo "Docker Compose plugin is available" docker compose version fi - name: Run plugin tests env: MAXIM_API_KEY: ${{ secrets.MAXIM_API_KEY }} MAXIM_LOGGER_ID: ${{ secrets.MAXIM_LOG_REPO_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }} AWS_ARN: ${{ secrets.AWS_ARN }} BEDROCK_API_KEY: ${{ secrets.BEDROCK_API_KEY }} AZURE_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }} AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} PARASAIL_API_KEY: ${{ secrets.PARASAIL_API_KEY }} ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }} SGL_API_KEY: ${{ secrets.SGL_API_KEY }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} VERTEX_CREDENTIALS: ${{ secrets.VERTEX_CREDENTIALS }} VERTEX_PROJECT_ID: ${{ secrets.VERTEX_PROJECT_ID }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} HUGGING_FACE_API_KEY: ${{ secrets.HUGGING_FACE_API_KEY }} BIFROST_ENCRYPTION_KEY: ${{ secrets.BIFROST_ENCRYPTION_KEY }} run: ./.github/workflows/scripts/test-all-plugins.sh test-bifrost-http: needs: [check-skip, detect-changes] if: needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.bifrost-http-needs-release == 'true' runs-on: ubuntu-latest permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > 172.38.0.12:8080 172.38.0.12:8301 172.38.0.2:5432 api.github.com:443 auth.docker.io:443 codecov.io:443 cr.weaviate.io:443 example.com:443 file.example.com:443 fonts.googleapis.com:443 fonts.gstatic.com:443 getbifrost.ai:443 github.com:443 nodejs.org:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 telemetry.qdrant.io:443 uploader.codecov.io:443 www.getbifrost.ai:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Set up Docker Compose run: | docker --version if ! docker compose version >/dev/null 2>&1; then echo "Installing Docker Compose..." sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version else echo "Docker Compose plugin is available" docker compose version fi - name: Run bifrost-http tests env: MAXIM_API_KEY: ${{ secrets.MAXIM_API_KEY }} MAXIM_LOGGER_ID: ${{ secrets.MAXIM_LOG_REPO_ID }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} BIFROST_ENCRYPTION_KEY: ${{ secrets.BIFROST_ENCRYPTION_KEY }} run: ./.github/workflows/scripts/test-bifrost-http.sh # Migration tests - validates database migrations from previous versions test-migrations: needs: [check-skip, detect-changes] if: needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.bifrost-http-needs-release == 'true' runs-on: ubuntu-latest permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > 172.38.0.2:5432 api.anthropic.com:443 api.github.com:443 api.openai.com:443 auth.docker.io:443 downloads.getmaxim.ai:443 getbifrost.ai:443 github.com:443 nodejs.org:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Set up Docker Compose run: | docker --version if ! docker compose version >/dev/null 2>&1; then echo "Installing Docker Compose..." sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version else echo "Docker Compose plugin is available" docker compose version fi - name: Run migration tests run: | chmod +x ./.github/workflows/scripts/run-migration-tests.sh ./.github/workflows/scripts/run-migration-tests.sh postgres # E2E UI tests - validates UI with Playwright test-e2e-ui: needs: [check-skip, detect-changes] if: needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.bifrost-http-needs-release == 'true' runs-on: ubuntu-latest permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > 172.38.0.12:8301 172.38.0.2:5432 _http._tcp.azure.archive.ubuntu.com:443 _https._tcp.esm.ubuntu.com:443 _https._tcp.motd.ubuntu.com:443 _https._tcp.packages.microsoft.com:443 api.github.com:443 api.openai.com:443 auth.docker.io:443 azure.archive.ubuntu.com:80 cdn.jsdelivr.net:443 cdn.playwright.dev:443 cr.weaviate.io:443 d3gk2c5xim1je2.cloudfront.net:443 d4tuoctqmanu0.cloudfront.net:443 docs.getbifrost.ai:443 esm.ubuntu.com:443 fonts.googleapis.com:443 fonts.gstatic.com:443 getbifrost.ai:443 github.com:443 mintcdn.com:443 nodejs.org:443 packages.microsoft.com:443 playwright.download.prss.microsoft.com:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 static.cloudflareinsights.com:443 storage.googleapis.com:443 sum.golang.org:443 telemetry.qdrant.io:443 ts-mcp-sse-proxy.fly.dev:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Set up Docker Compose run: | docker --version if ! docker compose version >/dev/null 2>&1; then echo "Installing Docker Compose..." sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version else echo "Docker Compose plugin is available" docker compose version fi - name: Run E2E UI tests env: MCP_SSE_HEADERS: ${{ secrets.MCP_SSE_HEADERS }} run: ./.github/workflows/scripts/test-e2e-ui.sh - name: Upload Playwright artifacts if: ${{ !cancelled() }} uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: playwright-report path: | tests/e2e/test-results/ tests/e2e/playwright-report/ retention-days: 30 # Docker image test - amd64 test-docker-image-amd64: needs: [check-skip, detect-changes] if: needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.docker-needs-release == 'true' runs-on: ubuntu-latest permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > api.anthropic.com:443 api.cerebras.ai:443 api.cohere.ai:443 api.elevenlabs.io:443 api.github.com:443 api.groq.com:443 api.mistral.ai:443 api.openai.com:443 api.parasail.io:443 api.replicate.com:443 auth.docker.io:443 bedrock.us-east-1.amazonaws.com:443 dl-cdn.alpinelinux.org:443 fonts.googleapis.com:443 fonts.gstatic.com:443 generativelanguage.googleapis.com:443 getbifrost.ai:443 ghcr.io:443 github.com:443 huggingface.co:443 maxim-o1.openai.azure.com:443 nodejs.org:443 openrouter.ai:443 pkg-containers.githubusercontent.com:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 telemetry.qdrant.io:443 www.getbifrost.ai:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Install Newman run: npm install -g newman newman-reporter-html - name: Setup Docker Buildx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Test Docker image (amd64) env: CI: "1" OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} VERTEX_PROJECT_ID: ${{ secrets.VERTEX_PROJECT_ID }} VERTEX_CREDENTIALS: ${{ secrets.VERTEX_CREDENTIALS }} GOOGLE_LOCATION: ${{ secrets.GOOGLE_LOCATION }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} PARASAIL_API_KEY: ${{ secrets.PARASAIL_API_KEY }} ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} HUGGING_FACE_API_KEY: ${{ secrets.HUGGING_FACE_API_KEY }} XAI_API_KEY: ${{ secrets.XAI_API_KEY }} REPLICATE_API_KEY: ${{ secrets.REPLICATE_API_KEY }} AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }} AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_REGION: ${{ secrets.AWS_REGION }} AWS_ARN: ${{ secrets.AWS_ARN }} run: | chmod +x ./.github/workflows/scripts/test-docker-image.sh ./.github/workflows/scripts/test-docker-image.sh linux/amd64 - name: Upload Newman reports if: ${{ !cancelled() }} uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: newman-reports-amd64 path: tests/e2e/api/newman-reports/ retention-days: 30 # Docker image test - arm64 test-docker-image-arm64: needs: [check-skip, detect-changes] if: needs.check-skip.outputs.should-skip != 'true' && needs.check-skip.outputs.skip-tests != 'true' && needs.detect-changes.outputs.docker-needs-release == 'true' runs-on: ubuntu-24.04-arm permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > api.anthropic.com:443 api.cerebras.ai:443 api.cohere.ai:443 api.elevenlabs.io:443 api.github.com:443 api.groq.com:443 api.mistral.ai:443 api.openai.com:443 api.parasail.io:443 api.replicate.com:443 auth.docker.io:443 bedrock.us-east-1.amazonaws.com:443 dl-cdn.alpinelinux.org:443 fonts.googleapis.com:443 fonts.gstatic.com:443 generativelanguage.googleapis.com:443 getbifrost.ai:443 ghcr.io:443 github.com:443 huggingface.co:443 maxim-o1.openai.azure.com:443 nodejs.org:443 openrouter.ai:443 pkg-containers.githubusercontent.com:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 telemetry.qdrant.io:443 www.getbifrost.ai:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Install Newman run: npm install -g newman newman-reporter-html - name: Setup Docker Buildx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Test Docker image (arm64) env: CI: "1" OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} VERTEX_PROJECT_ID: ${{ secrets.VERTEX_PROJECT_ID }} VERTEX_CREDENTIALS: ${{ secrets.VERTEX_CREDENTIALS }} GOOGLE_LOCATION: ${{ secrets.GOOGLE_LOCATION }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} PARASAIL_API_KEY: ${{ secrets.PARASAIL_API_KEY }} ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} HUGGING_FACE_API_KEY: ${{ secrets.HUGGING_FACE_API_KEY }} XAI_API_KEY: ${{ secrets.XAI_API_KEY }} REPLICATE_API_KEY: ${{ secrets.REPLICATE_API_KEY }} AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }} AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_REGION: ${{ secrets.AWS_REGION }} AWS_ARN: ${{ secrets.AWS_ARN }} run: | chmod +x ./.github/workflows/scripts/test-docker-image.sh ./.github/workflows/scripts/test-docker-image.sh linux/arm64 - name: Upload Newman reports if: ${{ !cancelled() }} uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: newman-reports-arm64 path: tests/e2e/api/newman-reports/ retention-days: 30 core-release: needs: [ check-skip, detect-changes, test-core, approve-flaky-test-core, test-framework, test-plugins, test-bifrost-http, test-migrations, test-docker-image-amd64, test-docker-image-arm64, ] if: "always() && needs.check-skip.outputs.should-skip != 'true' && needs.detect-changes.outputs.core-needs-release == 'true' && (needs.test-core.result == 'success' || needs.test-core.result == 'skipped' || (needs.test-core.result == 'failure' && needs.approve-flaky-test-core.result == 'success')) && (needs.test-framework.result == 'success' || needs.test-framework.result == 'skipped') && (needs.test-plugins.result == 'success' || needs.test-plugins.result == 'skipped') && (needs.test-bifrost-http.result == 'success' || needs.test-bifrost-http.result == 'skipped') && (needs.test-migrations.result == 'success' || needs.test-migrations.result == 'skipped') && (needs.test-docker-image-amd64.result == 'success' || needs.test-docker-image-amd64.result == 'skipped') && (needs.test-docker-image-arm64.result == 'success' || needs.test-docker-image-arm64.result == 'skipped')" runs-on: ubuntu-latest permissions: contents: write outputs: success: ${{ steps.release.outputs.success }} version: ${{ needs.detect-changes.outputs.core-version }} steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > api.github.com:443 github.com:443 nodejs.org:443 release-assets.githubusercontent.com:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true token: ${{ secrets.GH_TOKEN }} - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Configure Git run: | git config user.name "GitHub Actions Bot" git config user.email "github-actions[bot]@users.noreply.github.com" - name: Release core id: release env: GH_TOKEN: ${{ secrets.GH_TOKEN }} MAXIM_API_KEY: ${{ secrets.MAXIM_API_KEY }} MAXIM_LOGGER_ID: ${{ secrets.MAXIM_LOG_REPO_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }} AWS_ARN: ${{ secrets.AWS_ARN }} BEDROCK_API_KEY: ${{ secrets.BEDROCK_API_KEY }} AZURE_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }} AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} PARASAIL_API_KEY: ${{ secrets.PARASAIL_API_KEY }} ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }} SGL_API_KEY: ${{ secrets.SGL_API_KEY }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} VERTEX_CREDENTIALS: ${{ secrets.VERTEX_CREDENTIALS }} VERTEX_PROJECT_ID: ${{ secrets.VERTEX_PROJECT_ID }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} HUGGING_FACE_API_KEY: ${{ secrets.HUGGING_FACE_API_KEY }} AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} AWS_BEDROCK_ROLE_ARN: ${{ secrets.AWS_BEDROCK_ROLE_ARN }} REPLICATE_API_KEY: ${{ secrets.REPLICATE_API_KEY }} REPLICATE_OWNER: ${{ secrets.REPLICATE_OWNER }} RUNWAY_API_KEY : ${{ secrets.RUNWAY_API_KEY }} run: ./.github/workflows/scripts/release-core.sh "${{ needs.detect-changes.outputs.core-version }}" framework-release: needs: [ check-skip, detect-changes, test-core, approve-flaky-test-core, test-framework, test-plugins, test-bifrost-http, test-migrations, test-docker-image-amd64, test-docker-image-arm64, core-release, ] if: "always() && needs.check-skip.outputs.should-skip != 'true' && needs.detect-changes.outputs.framework-needs-release == 'true' && (needs.test-core.result == 'success' || needs.test-core.result == 'skipped' || (needs.test-core.result == 'failure' && needs.approve-flaky-test-core.result == 'success')) && (needs.test-framework.result == 'success' || needs.test-framework.result == 'skipped') && (needs.test-plugins.result == 'success' || needs.test-plugins.result == 'skipped') && (needs.test-bifrost-http.result == 'success' || needs.test-bifrost-http.result == 'skipped') && (needs.test-migrations.result == 'success' || needs.test-migrations.result == 'skipped') && (needs.test-docker-image-amd64.result == 'success' || needs.test-docker-image-amd64.result == 'skipped') && (needs.test-docker-image-arm64.result == 'success' || needs.test-docker-image-arm64.result == 'skipped') && (needs.detect-changes.outputs.core-needs-release == 'false' || needs.core-release.result == 'success' || needs.core-release.result == 'skipped')" runs-on: ubuntu-latest permissions: contents: write outputs: success: ${{ steps.release.outputs.success }} version: ${{ needs.detect-changes.outputs.framework-version }} steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > api.github.com:443 github.com:443 proxy.golang.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true token: ${{ secrets.GH_TOKEN }} - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Configure Git run: | git config user.name "GitHub Actions Bot" git config user.email "github-actions[bot]@users.noreply.github.com" - name: Set up Docker Compose run: | # Verify Docker is available docker --version # Install Docker Compose if not available as plugin if ! docker compose version >/dev/null 2>&1; then echo "Installing Docker Compose..." sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version else echo "Docker Compose plugin is available" docker compose version fi - name: Release framework id: release env: GH_TOKEN: ${{ secrets.GH_TOKEN }} MAXIM_API_KEY: ${{ secrets.MAXIM_API_KEY }} MAXIM_LOGGER_ID: ${{ secrets.MAXIM_LOG_REPO_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }} AWS_ARN: ${{ secrets.AWS_ARN }} BEDROCK_API_KEY: ${{ secrets.BEDROCK_API_KEY }} AZURE_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }} AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} PARASAIL_API_KEY: ${{ secrets.PARASAIL_API_KEY }} ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }} SGL_API_KEY: ${{ secrets.SGL_API_KEY }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} VERTEX_CREDENTIALS: ${{ secrets.VERTEX_CREDENTIALS }} VERTEX_PROJECT_ID: ${{ secrets.VERTEX_PROJECT_ID }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} HUGGING_FACE_API_KEY: ${{ secrets.HUGGING_FACE_API_KEY }} REPLICATE_API_KEY: ${{ secrets.REPLICATE_API_KEY }} REPLICATE_OWNER: ${{ secrets.REPLICATE_OWNER }} RUNWAY_API_KEY : ${{ secrets.RUNWAY_API_KEY }} run: ./.github/workflows/scripts/release-framework.sh "${{ needs.detect-changes.outputs.framework-version }}" plugins-release: needs: [ check-skip, detect-changes, test-core, approve-flaky-test-core, test-framework, test-plugins, test-bifrost-http, test-migrations, test-docker-image-amd64, test-docker-image-arm64, core-release, framework-release, ] if: "always() && needs.check-skip.outputs.should-skip != 'true' && needs.detect-changes.outputs.plugins-need-release == 'true' && (needs.test-core.result == 'success' || needs.test-core.result == 'skipped' || (needs.test-core.result == 'failure' && needs.approve-flaky-test-core.result == 'success')) && (needs.test-framework.result == 'success' || needs.test-framework.result == 'skipped') && (needs.test-plugins.result == 'success' || needs.test-plugins.result == 'skipped') && (needs.test-bifrost-http.result == 'success' || needs.test-bifrost-http.result == 'skipped') && (needs.test-migrations.result == 'success' || needs.test-migrations.result == 'skipped') && (needs.test-docker-image-amd64.result == 'success' || needs.test-docker-image-amd64.result == 'skipped') && (needs.test-docker-image-arm64.result == 'success' || needs.test-docker-image-arm64.result == 'skipped') && (needs.detect-changes.outputs.core-needs-release == 'false' || needs.core-release.result == 'success' || needs.core-release.result == 'skipped') && (needs.detect-changes.outputs.framework-needs-release == 'false' || needs.framework-release.result == 'success' || needs.framework-release.result == 'skipped')" runs-on: ubuntu-latest permissions: contents: write outputs: success: ${{ steps.release.outputs.success }} steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > _http._tcp.azure.archive.ubuntu.com:443 _https._tcp.esm.ubuntu.com:443 _https._tcp.motd.ubuntu.com:443 _https._tcp.packages.microsoft.com:443 api.github.com:443 azure.archive.ubuntu.com:80 esm.ubuntu.com:443 github.com:443 nodejs.org:443 packages.microsoft.com:443 proxy.golang.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true token: ${{ secrets.GH_TOKEN }} - name: Install jq run: | sudo apt-get update sudo apt-get install -y jq - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Configure Git run: | git config user.name "GitHub Actions Bot" git config user.email "github-actions[bot]@users.noreply.github.com" - name: Set up Docker Compose run: | # Verify Docker is available docker --version # Install Docker Compose if not available as plugin if ! docker compose version >/dev/null 2>&1; then echo "Installing Docker Compose..." sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version else echo "Docker Compose plugin is available" docker compose version fi - name: Release all changed plugins id: release env: GH_TOKEN: ${{ secrets.GH_TOKEN }} MAXIM_API_KEY: ${{ secrets.MAXIM_API_KEY }} MAXIM_LOGGER_ID: ${{ secrets.MAXIM_LOG_REPO_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }} AWS_ARN: ${{ secrets.AWS_ARN }} BEDROCK_API_KEY: ${{ secrets.BEDROCK_API_KEY }} AZURE_ENDPOINT: ${{ secrets.AZURE_ENDPOINT }} AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} PARASAIL_API_KEY: ${{ secrets.PARASAIL_API_KEY }} ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }} PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }} SGL_API_KEY: ${{ secrets.SGL_API_KEY }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} VERTEX_CREDENTIALS: ${{ secrets.VERTEX_CREDENTIALS }} VERTEX_PROJECT_ID: ${{ secrets.VERTEX_PROJECT_ID }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} HUGGING_FACE_API_KEY: ${{ secrets.HUGGING_FACE_API_KEY }} REPLICATE_API_KEY: ${{ secrets.REPLICATE_API_KEY }} REPLICATE_OWNER: ${{ secrets.REPLICATE_OWNER }} RUNWAY_API_KEY : ${{ secrets.RUNWAY_API_KEY }} run: ./.github/workflows/scripts/release-all-plugins.sh '${{ needs.detect-changes.outputs.changed-plugins }}' # Prep: update dependencies, validate build, commit/push bifrost-http-prep: needs: [ check-skip, detect-changes, test-core, approve-flaky-test-core, test-framework, test-plugins, test-bifrost-http, test-migrations, test-docker-image-amd64, test-docker-image-arm64, core-release, framework-release, plugins-release, ] if: "always() && needs.check-skip.outputs.should-skip != 'true' && needs.detect-changes.outputs.bifrost-http-needs-release == 'true' && (needs.test-core.result == 'success' || needs.test-core.result == 'skipped' || (needs.test-core.result == 'failure' && needs.approve-flaky-test-core.result == 'success')) && (needs.test-framework.result == 'success' || needs.test-framework.result == 'skipped') && (needs.test-plugins.result == 'success' || needs.test-plugins.result == 'skipped') && (needs.test-bifrost-http.result == 'success' || needs.test-bifrost-http.result == 'skipped') && (needs.test-migrations.result == 'success' || needs.test-migrations.result == 'skipped') && (needs.test-docker-image-amd64.result == 'success' || needs.test-docker-image-amd64.result == 'skipped') && (needs.test-docker-image-arm64.result == 'success' || needs.test-docker-image-arm64.result == 'skipped') && (needs.detect-changes.outputs.core-needs-release == 'false' || needs.core-release.result == 'success' || needs.core-release.result == 'skipped') && (needs.detect-changes.outputs.framework-needs-release == 'false' || needs.framework-release.result == 'success' || needs.framework-release.result == 'skipped') && (needs.detect-changes.outputs.plugins-need-release == 'false' || needs.plugins-release.result == 'success' || needs.plugins-release.result == 'skipped')" runs-on: ubuntu-latest permissions: contents: write outputs: success: ${{ steps.prep.outputs.success }} steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > api.github.com:443 fonts.googleapis.com:443 fonts.gstatic.com:443 github.com:443 nodejs.org:443 proxy.golang.org:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true token: ${{ secrets.GH_TOKEN }} - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Configure Git run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - name: Prep bifrost-http release id: prep env: GH_TOKEN: ${{ secrets.GH_TOKEN }} run: ./.github/workflows/scripts/release-bifrost-http-prep.sh "${{ needs.detect-changes.outputs.transport-version }}" # Build darwin, windows, linux/amd64 binaries and upload to R2 build-binaries-x86: needs: [bifrost-http-prep, detect-changes] if: "always() && needs.bifrost-http-prep.result == 'success' && needs.bifrost-http-prep.outputs.success == 'true'" runs-on: ubuntu-latest permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > 7defe2860d5ee49a1e667e1eeea34b25.r2.cloudflarestorage.com:443 _http._tcp.azure.archive.ubuntu.com:443 _https._tcp.esm.ubuntu.com:443 _https._tcp.motd.ubuntu.com:443 _https._tcp.packages.microsoft.com:443 api.github.com:443 azure.archive.ubuntu.com:80 esm.ubuntu.com:443 files.pythonhosted.org:443 fonts.googleapis.com:443 fonts.gstatic.com:443 github.com:443 nodejs.org:443 packages.microsoft.com:443 proxy.golang.org:443 pypi.org:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true token: ${{ secrets.GH_TOKEN }} - name: Pull latest changes run: git pull origin ${{ github.ref_name }} - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Build UI run: make build-ui - name: Install cross-compilation toolchains run: bash ./.github/workflows/scripts/install-cross-compilers.sh - name: Build executables run: bash ./.github/workflows/scripts/build-executables.sh "${{ needs.detect-changes.outputs.transport-version }}" "darwin/amd64 darwin/arm64 linux/amd64 windows/amd64" - name: Configure R2 env: R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} run: bash ./.github/workflows/scripts/configure-r2.sh - name: Upload to R2 env: R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} R2_BUCKET: ${{ secrets.R2_BUCKET }} SKIP_LATEST_UPLOAD: "true" run: bash ./.github/workflows/scripts/upload-to-r2.sh "transports/v${{ needs.detect-changes.outputs.transport-version }}" # Build linux/arm64 natively on ARM runner and upload to R2 build-binaries-arm64: needs: [bifrost-http-prep, detect-changes] if: "always() && needs.bifrost-http-prep.result == 'success' && needs.bifrost-http-prep.outputs.success == 'true'" runs-on: ubuntu-24.04-arm permissions: contents: read steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > 7defe2860d5ee49a1e667e1eeea34b25.r2.cloudflarestorage.com:443 api.github.com:443 files.pythonhosted.org:443 fonts.googleapis.com:443 fonts.gstatic.com:443 github.com:443 nodejs.org:443 proxy.golang.org:443 pypi.org:443 registry.npmjs.org:443 release-assets.githubusercontent.com:443 storage.googleapis.com:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true token: ${{ secrets.GH_TOKEN }} - name: Pull latest changes run: git pull origin ${{ github.ref_name }} - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "1.26.2" - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "25" - name: Build UI run: make build-ui - name: Build linux/arm64 binary run: bash ./.github/workflows/scripts/build-executables.sh "${{ needs.detect-changes.outputs.transport-version }}" "linux/arm64" - name: Configure R2 env: R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} run: bash ./.github/workflows/scripts/configure-r2.sh - name: Upload to R2 env: R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} R2_BUCKET: ${{ secrets.R2_BUCKET }} SKIP_LATEST_UPLOAD: "true" run: bash ./.github/workflows/scripts/upload-to-r2.sh "transports/v${{ needs.detect-changes.outputs.transport-version }}" # Finalize: changelog, tagging, GitHub release, R2 latest copy bifrost-http-release: needs: [build-binaries-x86, build-binaries-arm64, detect-changes, bifrost-http-prep] if: "always() && needs.build-binaries-x86.result == 'success' && needs.build-binaries-arm64.result == 'success'" runs-on: ubuntu-latest permissions: contents: write outputs: success: ${{ steps.release.outputs.success }} version: ${{ needs.detect-changes.outputs.transport-version }} steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > 7defe2860d5ee49a1e667e1eeea34b25.r2.cloudflarestorage.com:443 api.github.com:443 files.pythonhosted.org:443 github.com:443 pypi.org:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true token: ${{ secrets.GH_TOKEN }} - name: Pull latest changes run: git pull origin ${{ github.ref_name }} - name: Configure R2 env: R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} run: bash ./.github/workflows/scripts/configure-r2.sh - name: Finalize bifrost-http release id: release env: GH_TOKEN: ${{ secrets.GH_TOKEN }} R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} R2_BUCKET: ${{ secrets.R2_BUCKET }} run: ./.github/workflows/scripts/release-bifrost-http-finalize.sh "${{ needs.detect-changes.outputs.transport-version }}" # Docker build amd64 docker-build-amd64: needs: [ check-skip, detect-changes, test-core, approve-flaky-test-core, test-framework, test-plugins, test-bifrost-http, test-migrations, test-docker-image-amd64, test-docker-image-arm64, core-release, framework-release, plugins-release, bifrost-http-release, ] if: "always() && needs.check-skip.outputs.should-skip != 'true' && needs.detect-changes.outputs.docker-needs-release == 'true' && (needs.test-core.result == 'success' || needs.test-core.result == 'skipped' || (needs.test-core.result == 'failure' && needs.approve-flaky-test-core.result == 'success')) && (needs.test-framework.result == 'success' || needs.test-framework.result == 'skipped') && (needs.test-plugins.result == 'success' || needs.test-plugins.result == 'skipped') && (needs.test-bifrost-http.result == 'success' || needs.test-bifrost-http.result == 'skipped') && (needs.test-migrations.result == 'success' || needs.test-migrations.result == 'skipped') && (needs.test-docker-image-amd64.result == 'success' || needs.test-docker-image-amd64.result == 'skipped') && (needs.test-docker-image-arm64.result == 'success' || needs.test-docker-image-arm64.result == 'skipped') && (needs.detect-changes.outputs.core-needs-release == 'false' || needs.core-release.result == 'success' || needs.core-release.result == 'skipped') && (needs.detect-changes.outputs.framework-needs-release == 'false' || needs.framework-release.result == 'success' || needs.framework-release.result == 'skipped') && (needs.detect-changes.outputs.plugins-need-release == 'false' || needs.plugins-release.result == 'success' || needs.plugins-release.result == 'skipped') && (needs.detect-changes.outputs.bifrost-http-needs-release == 'false' || needs.bifrost-http-release.result == 'success' || needs.bifrost-http-release.result == 'skipped')" runs-on: ubuntu-latest permissions: contents: write env: REGISTRY: docker.io ACCOUNT: maximhq IMAGE_NAME: bifrost steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > auth.docker.io:443 dl-cdn.alpinelinux.org:443 fonts.googleapis.com:443 fonts.gstatic.com:443 github.com:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 registry.npmjs.org:443 storage.googleapis.com:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Verify bifrost-http release id: verify continue-on-error: true env: GH_TOKEN: ${{ secrets.GH_TOKEN }} run: | ./.github/workflows/scripts/verify-bifrost-http-release.sh "${{ needs.detect-changes.outputs.transport-version }}" "${{ needs.detect-changes.outputs.bifrost-http-needs-release }}" echo "verified=true" >> $GITHUB_OUTPUT - name: Setup Docker Buidx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Log in to Docker Hub uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Determine Docker tags id: tags run: | git pull origin ${{ github.ref_name }} VERSION="${{ needs.detect-changes.outputs.transport-version }}" BASE_TAG="${{ env.REGISTRY }}/${{ env.ACCOUNT }}/${{ env.IMAGE_NAME }}:v${VERSION}-amd64" echo "tags=${BASE_TAG}" >> $GITHUB_OUTPUT - name: Build and push AMD64 Docker image uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . build-args: | VERSION=${{ needs.detect-changes.outputs.transport-version }} file: ./transports/Dockerfile push: true tags: ${{ steps.tags.outputs.tags }} platforms: linux/amd64 # Docker build arm64 docker-build-arm64: needs: [ check-skip, detect-changes, test-core, approve-flaky-test-core, test-framework, test-plugins, test-bifrost-http, test-migrations, test-docker-image-amd64, test-docker-image-arm64, core-release, framework-release, plugins-release, bifrost-http-release, ] if: "always() && needs.check-skip.outputs.should-skip != 'true' && needs.detect-changes.outputs.docker-needs-release == 'true' && (needs.test-core.result == 'success' || needs.test-core.result == 'skipped' || (needs.test-core.result == 'failure' && needs.approve-flaky-test-core.result == 'success')) && (needs.test-framework.result == 'success' || needs.test-framework.result == 'skipped') && (needs.test-plugins.result == 'success' || needs.test-plugins.result == 'skipped') && (needs.test-bifrost-http.result == 'success' || needs.test-bifrost-http.result == 'skipped') && (needs.test-migrations.result == 'success' || needs.test-migrations.result == 'skipped') && (needs.test-docker-image-amd64.result == 'success' || needs.test-docker-image-amd64.result == 'skipped') && (needs.test-docker-image-arm64.result == 'success' || needs.test-docker-image-arm64.result == 'skipped') && (needs.detect-changes.outputs.core-needs-release == 'false' || needs.core-release.result == 'success' || needs.core-release.result == 'skipped') && (needs.detect-changes.outputs.framework-needs-release == 'false' || needs.framework-release.result == 'success' || needs.framework-release.result == 'skipped') && (needs.detect-changes.outputs.plugins-need-release == 'false' || needs.plugins-release.result == 'success' || needs.plugins-release.result == 'skipped') && (needs.detect-changes.outputs.bifrost-http-needs-release == 'false' || needs.bifrost-http-release.result == 'success' || needs.bifrost-http-release.result == 'skipped')" runs-on: ubuntu-24.04-arm permissions: contents: write env: REGISTRY: docker.io ACCOUNT: maximhq IMAGE_NAME: bifrost steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > auth.docker.io:443 dl-cdn.alpinelinux.org:443 fonts.googleapis.com:443 fonts.gstatic.com:443 github.com:443 production.cloudflare.docker.com:443 proxy.golang.org:443 registry-1.docker.io:443 registry.npmjs.org:443 storage.googleapis.com:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true - name: Verify bifrost-http release id: verify continue-on-error: true env: GH_TOKEN: ${{ secrets.GH_TOKEN }} run: | ./.github/workflows/scripts/verify-bifrost-http-release.sh "${{ needs.detect-changes.outputs.transport-version }}" "${{ needs.detect-changes.outputs.bifrost-http-needs-release }}" echo "verified=true" >> $GITHUB_OUTPUT - name: Setup Docker Buidx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Log in to Docker Hub uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Determine Docker tags id: tags run: | git pull origin ${{ github.ref_name }} VERSION="${{ needs.detect-changes.outputs.transport-version }}" BASE_TAG="${{ env.REGISTRY }}/${{ env.ACCOUNT }}/${{ env.IMAGE_NAME }}:v${VERSION}-arm64" echo "tags=${BASE_TAG}" >> $GITHUB_OUTPUT - name: Build and push ARM64 Docker image uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: ./transports/Dockerfile push: true build-args: | VERSION=${{ needs.detect-changes.outputs.transport-version }} tags: ${{ steps.tags.outputs.tags }} platforms: linux/arm64 # Docker manifest docker-manifest: needs: [check-skip, detect-changes, docker-build-amd64, docker-build-arm64] if: "always() && needs.check-skip.outputs.should-skip != 'true' && needs.docker-build-amd64.result == 'success' && needs.docker-build-arm64.result == 'success'" runs-on: ubuntu-latest env: REGISTRY: docker.io ACCOUNT: maximhq IMAGE_NAME: bifrost steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > auth.docker.io:443 github.com:443 production.cloudflare.docker.com:443 registry-1.docker.io:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Log in to Docker Hub uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Create and push multi-arch manifest run: | ./.github/workflows/scripts/create-docker-manifest.sh "${{ needs.detect-changes.outputs.transport-version }}" # Push Mintlify changelog push-mintlify-changelog: needs: [ check-skip, detect-changes, test-core, approve-flaky-test-core, test-framework, test-plugins, test-bifrost-http, test-migrations, test-docker-image-amd64, test-docker-image-arm64, core-release, framework-release, plugins-release, bifrost-http-release, ] if: "always() && needs.check-skip.outputs.should-skip != 'true' && (needs.test-core.result == 'success' || needs.test-core.result == 'skipped' || (needs.test-core.result == 'failure' && needs.approve-flaky-test-core.result == 'success')) && (needs.test-framework.result == 'success' || needs.test-framework.result == 'skipped') && (needs.test-plugins.result == 'success' || needs.test-plugins.result == 'skipped') && (needs.test-bifrost-http.result == 'success' || needs.test-bifrost-http.result == 'skipped') && (needs.test-migrations.result == 'success' || needs.test-migrations.result == 'skipped') && (needs.test-docker-image-amd64.result == 'success' || needs.test-docker-image-amd64.result == 'skipped') && (needs.test-docker-image-arm64.result == 'success' || needs.test-docker-image-arm64.result == 'skipped') && (needs.detect-changes.outputs.core-needs-release == 'false' || needs.core-release.result == 'success' || needs.core-release.result == 'skipped') && (needs.detect-changes.outputs.framework-needs-release == 'false' || needs.framework-release.result == 'success' || needs.framework-release.result == 'skipped') && (needs.detect-changes.outputs.plugins-need-release == 'false' || needs.plugins-release.result == 'success' || needs.plugins-release.result == 'skipped') && (needs.detect-changes.outputs.bifrost-http-needs-release == 'false' || needs.bifrost-http-release.result == 'success' || needs.bifrost-http-release.result == 'skipped')" runs-on: ubuntu-latest permissions: contents: write steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > github.com:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 fetch-tags: true token: ${{ secrets.GH_TOKEN }} - name: Push Mintlify changelog run: | ./.github/workflows/scripts/push-mintlify-changelog.sh "${{ needs.detect-changes.outputs.transport-version }}" # Notification notify: needs: [ check-skip, detect-changes, test-core, test-framework, test-plugins, test-bifrost-http, test-migrations, test-docker-image-amd64, test-docker-image-arm64, core-release, framework-release, plugins-release, bifrost-http-release, docker-manifest, ] if: "always() && needs.check-skip.outputs.should-skip != 'true'" runs-on: ubuntu-latest steps: - name: Harden Runner uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 with: egress-policy: block allowed-endpoints: > _http._tcp.azure.archive.ubuntu.com:443 _https._tcp.esm.ubuntu.com:443 _https._tcp.motd.ubuntu.com:443 _https._tcp.packages.microsoft.com:443 azure.archive.ubuntu.com:80 discord.com:443 dl.google.com:443 esm.ubuntu.com:443 packages.microsoft.com:443 - name: Install jq run: | sudo apt-get update sudo apt-get install -y jq - name: Discord Notification env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} run: | # Build status summary CORE_STATUS="⏭️ Skipped" FRAMEWORK_STATUS="⏭️ Skipped" PLUGINS_STATUS="⏭️ Skipped" BIFROST_STATUS="⏭️ Skipped" if [ "${{ needs.core-release.result }}" = "success" ]; then CORE_STATUS="✅ Released v${{ needs.detect-changes.outputs.core-version }}" elif [ "${{ needs.core-release.result }}" = "failure" ]; then CORE_STATUS="❌ Failed" fi if [ "${{ needs.framework-release.result }}" = "success" ]; then FRAMEWORK_STATUS="✅ Released v${{ needs.detect-changes.outputs.framework-version }}" elif [ "${{ needs.framework-release.result }}" = "failure" ]; then FRAMEWORK_STATUS="❌ Failed" fi if [ "${{ needs.plugins-release.result }}" = "success" ]; then PLUGINS_STATUS="✅ Released plugins" elif [ "${{ needs.plugins-release.result }}" = "failure" ]; then PLUGINS_STATUS="❌ Failed" fi if [ "${{ needs.bifrost-http-release.result }}" = "success" ]; then BIFROST_STATUS="✅ Released v${{ needs.detect-changes.outputs.transport-version }}" elif [ "${{ needs.bifrost-http-release.result }}" = "failure" ]; then BIFROST_STATUS="❌ Failed" fi # Build the message with proper formatting MESSAGE=$(printf "🚀 **Release Pipeline Complete**\n\n**Components:**\n• Core: %s\n• Framework: %s\n• Plugins: %s\n• Bifrost HTTP: %s\n\n**Details:**\n• Branch: \`${{ github.ref_name }}\`\n• Commit: \`%.8s\`\n• Author: %s\n\n[View Workflow Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" "$CORE_STATUS" "$FRAMEWORK_STATUS" "$PLUGINS_STATUS" "$BIFROST_STATUS" "${{ github.sha }}" "${{ github.actor }}") payload="$(jq -n --arg content "$MESSAGE" '{content:$content}')" curl -sS -H "Content-Type: application/json" -d "$payload" "$DISCORD_WEBHOOK"