name: CI on: push: branches: [main, master] pull_request: branches: [main, master] jobs: changes: runs-on: ubuntu-latest outputs: openapi: ${{ steps.detect.outputs.openapi }} code: ${{ steps.detect.outputs.code }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - id: detect name: Detect changed paths (OpenAPI vs doc-only vs code) run: | set -euo pipefail openapi=false code=true if [ "${{ github.event_name }}" = "pull_request" ]; then base="${{ github.event.pull_request.base.sha }}" head="${{ github.event.pull_request.head.sha }}" FILES="$(git diff --name-only "$base" "$head")" else before="${{ github.event.before }}" after="${{ github.sha }}" if [ -n "$before" ] && [ "$before" != "0000000000000000000000000000000000000000" ]; then FILES="$(git diff --name-only "$before" "$after")" elif git rev-parse --verify HEAD~1 >/dev/null 2>&1; then FILES="$(git diff --name-only HEAD~1 HEAD)" else # Нет родителя (первый коммит / тонкий clone) — полный пайплайн + OpenAPI openapi=true code=true echo "openapi=$openapi" >> "$GITHUB_OUTPUT" echo "code=$code" >> "$GITHUB_OUTPUT" echo "No parent commit: openapi=true code=true" exit 0 fi fi # Пустой diff (редко) — не отключаем сборку из осторожности if [ -z "$(printf '%s' "$FILES" | tr -d '[:space:]')" ]; then openapi=false code=true echo "openapi=$openapi" >> "$GITHUB_OUTPUT" echo "code=$code" >> "$GITHUB_OUTPUT" echo "Empty diff: openapi=false code=true" exit 0 fi if printf '%s\n' "$FILES" | grep -qE '^docs/openapi\.yaml$|^redocly\.yaml$'; then openapi=true fi doc_only_all=true while IFS= read -r f || [ -n "${f:-}" ]; do [ -z "${f:-}" ] && continue if [[ "$f" == "README.md" || "$f" == ".gitea/README.md" || "$f" == "web/README.md" || "$f" == "redocly.yaml" || "$f" == docs/* ]]; then continue fi doc_only_all=false break done <<< "$FILES" if $doc_only_all; then code=false else code=true fi echo "openapi=$openapi" >> "$GITHUB_OUTPUT" echo "code=$code" >> "$GITHUB_OUTPUT" echo "Changed files (first 20):" printf '%s\n' "$FILES" | head -n 20 echo "openapi=$openapi code=$code" openapi: needs: [changes] if: needs.changes.outputs.openapi == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - name: Lint OpenAPI (Redocly) run: npx --yes @redocly/cli@1 lint docs/openapi.yaml go: needs: [changes] if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.22" - name: Vet run: go vet ./... - name: Test run: go test ./... -race -count=1 - name: Build all commands run: | set -euxo pipefail out="${RUNNER_TEMP}/evobgp-bin" mkdir -p "$out" for d in cmd/*/; do name="$(basename "$d")" go build -o "$out/$name" "./$d" done bird2: runs-on: ubuntu-latest needs: [go] steps: - uses: actions/checkout@v4 # Вложенный docker + bind-mount ломается, если демон Docker на хосте не видит путь # workspace runner'а (/workspace/...). bird -p на самом job-раннере надёжнее. - name: Install bird2 run: | set -euxo pipefail if command -v sudo >/dev/null 2>&1; then SUDO=sudo; else SUDO=""; fi $SUDO apt-get update -qq DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq bird2 bird --version - name: bird -p on all scenario bird.conf files env: WORKSPACE: ${{ github.workspace }} run: | set -euxo pipefail WS="${WORKSPACE:-$PWD}" cd "$WS" if [ ! -f internal/birdfmt/testdata/scenarios/minimal/bird.conf ]; then echo "Нет сценариев BIRD в checkout. Проверьте, что internal/birdfmt/testdata/scenarios закоммичен и push в remote." ls -la internal/birdfmt/testdata/ 2>/dev/null || ls -la exit 1 fi for conf in internal/birdfmt/testdata/scenarios/*/bird.conf; do echo "==> $conf" bird -c "$WS/$conf" -p done # Сборка образов и push в Container Registry Gitea (только push в main/master; см. .gitea/README.md). docker-images: needs: [go] if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - image: evobgp-api dockerfile: deploy/docker/gobinary/Dockerfile bin: evobgp-api birdc: "1" - image: evobgp-all dockerfile: deploy/docker/gobinary/Dockerfile bin: evobgp-all birdc: "1" - image: evobgp-scheduler dockerfile: deploy/docker/gobinary/Dockerfile bin: evobgp-scheduler birdc: "0" - image: evobgp-ingest dockerfile: deploy/docker/gobinary/Dockerfile bin: evobgp-ingest birdc: "0" - image: evobgp-render dockerfile: deploy/docker/gobinary/Dockerfile bin: evobgp-render birdc: "0" - image: evobgp-deploy dockerfile: deploy/docker/gobinary/Dockerfile bin: evobgp-deploy birdc: "0" - image: evobgp-node dockerfile: deploy/docker/gobinary/Dockerfile bin: evobgp-node birdc: "0" - image: evobgp-web dockerfile: deploy/docker/evobgp-web/Dockerfile - image: evobgp-agent dockerfile: deploy/docker/evobgp-agent/Dockerfile - image: evobgp-bird2 dockerfile: deploy/docker/bird2/Dockerfile steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Prepare image metadata id: meta run: | set -euo pipefail owner_lc="$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" echo "owner_lc=$owner_lc" >> "$GITHUB_OUTPUT" short_sha="$(echo '${{ github.sha }}' | cut -c1-7)" echo "short_sha=$short_sha" >> "$GITHUB_OUTPUT" echo "docker_push=true" >> "$GITHUB_OUTPUT" - name: Log in to Gitea Registry if: steps.meta.outputs.docker_push == 'true' uses: docker/login-action@v3 with: registry: git.shts.su username: ${{ gitea.actor }} # PAT репозитория или встроенный токен job (нужны права на пакеты в настройках Actions). password: ${{ secrets.ACTIONS_PAT || gitea.token }} - name: Build and push ${{ matrix.image }} env: OWNER_LC: ${{ steps.meta.outputs.owner_lc }} SHORT_SHA: ${{ steps.meta.outputs.short_sha }} DO_PUSH: ${{ steps.meta.outputs.docker_push }} DF: ${{ matrix.dockerfile }} IMAGE: ${{ matrix.image }} BIN: ${{ matrix.bin }} BIRDC: ${{ matrix.birdc }} run: | set -euxo pipefail WS="${{ github.workspace }}" cd "$WS" TAG_LOCAL="evobgp:${IMAGE}-${SHORT_SHA}" BUILD_ARGS=() if [ -n "${BIN:-}" ]; then BUILD_ARGS+=(--build-arg "BIN=${BIN}") BUILD_ARGS+=(--build-arg "INSTALL_BIRDC=${BIRDC:-0}") fi if [ "$DO_PUSH" = "true" ]; then IMG="git.shts.su/${OWNER_LC}/${IMAGE}" docker buildx build \ --platform linux/amd64 \ --file "$DF" \ "${BUILD_ARGS[@]}" \ --tag "${IMG}:latest" \ --tag "${IMG}:${SHORT_SHA}" \ --tag "${IMG}:sha-${{ github.sha }}" \ --push \ "$WS" else docker buildx build \ --platform linux/amd64 \ --file "$DF" \ "${BUILD_ARGS[@]}" \ --tag "$TAG_LOCAL" \ --load \ "$WS" fi