Skip to content

[ENG-2795] Relay cloud datasource capture, management and availability #1630

[ENG-2795] Relay cloud datasource capture, management and availability

[ENG-2795] Relay cloud datasource capture, management and availability #1630

name: Dev - Build and Deploy on PR
# Trigger-shaped caller. The build lives in build-deploy.yml; this file holds the
# trigger, the gate, and the PR-only checks.
on:
pull_request:
types: [opened, reopened, synchronize, labeled, unlabeled]
permissions:
contents: read
defaults:
run:
shell: bash
# Cancel any existing runs of this workflow on the same branch/pr
# We always want to build/deploy/test a new commit over an older one
concurrency:
group: ${{ github.workflow_ref }}
cancel-in-progress: true
jobs:
# One gate answering "should this pipeline run at all", for two reasons that
# both used to be handled elsewhere or not at all.
#
# FORK PRs. This repo is PUBLIC and `mdb-dev` is a pod inside the newdev cluster
# with IRSA into the build/ECR account, so without a guard a pull request from
# any GitHub account executes its own code there. Fork PRs get no secrets and a
# read-only token, but the runner itself is the prize: cloud credentials, a
# network position inside the cluster, and a tool cache later internal jobs
# reuse. GitHub's first-time-contributor approval does not cover anyone with a
# merged PR.
#
# PROMOTION PRs. A `staging` -> `main` PR promotes commits the staging pipeline
# already built and tested, so rebuilding them here produces an image nothing
# will deploy. This cannot be a trigger filter: for `pull_request`, GitHub's
# `branches` filters match the pull request's BASE branch, and the only lever on
# the head branch is a job-level conditional.
gate:
runs-on: ubuntu-latest
outputs:
run: ${{ steps.decide.outputs.run }}
steps:
- name: Decide whether this PR needs the pipeline
id: decide
env:
HEAD_REF: ${{ github.head_ref }}
BASE_REF: ${{ github.base_ref }}
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
THIS_REPO: ${{ github.repository }}
run: |
set -euo pipefail
if [ "$HEAD_REPO" != "$THIS_REPO" ]; then
echo "run=false" >> "$GITHUB_OUTPUT"
{
echo "### Build skipped: fork pull request"
echo
echo "The image build runs on a self-hosted runner inside our cluster, so it"
echo "does not execute code from a fork. The unit tests below still run."
} >> "$GITHUB_STEP_SUMMARY"
elif [ "$HEAD_REF" = "staging" ] || [ "$HEAD_REF" = "main" ]; then
echo "run=false" >> "$GITHUB_OUTPUT"
{
echo "### Build skipped: promotion PR"
echo
echo "\`$HEAD_REF\` -> \`$BASE_REF\` promotes commits the \`$HEAD_REF\`"
echo "pipeline already built and tested."
} >> "$GITHUB_STEP_SUMMARY"
else
echo "run=true" >> "$GITHUB_OUTPUT"
fi
run-unit-tests:
# Deliberately ungated: these run on `ubuntu-latest` with no secrets, so a
# fork contributor gets the CI that matters to them.
uses: ./.github/workflows/tests-unit.yml
wheels-available:
# Ungated for the same reason as the unit tests: GitHub-hosted, secret-free,
# and this is the check a fork contributor most needs, since it fails on a
# platform they are unlikely to own.
permissions:
contents: read
uses: ./.github/workflows/wheels-available.yml
workflow-lint:
# actionlint, the caller/callee permission check, and a zizmor audit, from the
# one place every service repo shares. Ungated for the same reason as the unit
# tests: GitHub-hosted, secret-free, and useful on a fork PR.
permissions:
contents: read
uses: mindsdb/github-actions/.github/workflows/workflow-lint.yml@main
with:
default-permissions: read
secrets: inherit
build-deploy:
needs: [gate]
if: needs.gate.outputs.run == 'true'
permissions:
contents: read
uses: ./.github/workflows/build-deploy.yml
with:
build-environment: development
pr-environment: true
secrets: inherit
pr-env-comment:
# Where the PR environment is. Called from HERE rather than from inside
# build-deploy.yml, because this is the only caller that should hold
# `pull-requests: write` — putting it in the shared pipeline would force the
# staging and prod callers to grant a PR scope on the release path just so the
# file would load.
#
# The rendering is shared so every repo's comment looks the same; the host
# pattern stays here, because mindsdb/github-actions is public.
needs: [gate, build-deploy]
# Only when an environment actually exists. `build-deploy` succeeding does not
# mean one does: with no `deploy` label the rollout is skipped and every other
# job still passes, which posted a comment full of URLs for an env nobody had
# created.
if: ${{ !cancelled() && needs.gate.outputs.run == 'true' }}
permissions:
contents: read
pull-requests: write
uses: mindsdb/github-actions/.github/workflows/pr-env-comment.yml@main
with:
env-name: pr-cowork-server-${{ github.event.pull_request.number }}
status: ${{ needs.build-deploy.outputs.pr-env-deployed == 'true' && 'up' || 'absent' }}
# cowork-server is PUBLIC, so the reusable drops this and the notes anyway.
# Passed for the day the repo is not, and so the caller reads the same as
# the others.
access-doc-url: https://github.com/mindsdb/internal-documentation/blob/main/pr-environments.md
links: '[{"label":"Health","url":"https://cowork-pr-cowork-server-${{ github.event.pull_request.number }}.dev.mindshub.ai/api/v1/health/"}]'
notes: >-
The desktop app does not consume this environment: it installs cowork-server
from PyPI or git per channel, so a PR env is for exercising the HTTP surface
directly.
secrets: inherit