# Orchestrator Pipeline - Mosaic Stack # Quality gates, build, and Docker publish for @mosaic/orchestrator # # Triggers on: apps/orchestrator/**, packages/**, root configs # Security chain: source audit + Trivy container scan when: - event: [push, pull_request, manual] path: include: - "apps/orchestrator/**" - "packages/**" - "pnpm-lock.yaml" - "pnpm-workspace.yaml" - "turbo.json" - "package.json" - ".woodpecker/orchestrator.yml" - ".trivyignore" variables: - &node_image "node:24-alpine" - &install_deps | corepack enable pnpm install --frozen-lockfile - &use_deps | corepack enable - &turbo_env TURBO_API: from_secret: turbo_api TURBO_TOKEN: from_secret: turbo_token TURBO_TEAM: from_secret: turbo_team - &kaniko_setup | mkdir -p /kaniko/.docker echo "{\"auths\":{\"git.mosaicstack.dev\":{\"username\":\"$GITEA_USER\",\"password\":\"$GITEA_TOKEN\"}}}" > /kaniko/.docker/config.json steps: # === Quality Gates === install: image: *node_image commands: - *install_deps security-audit: image: *node_image commands: - *use_deps - pnpm audit --audit-level=high depends_on: - install lint: image: *node_image environment: SKIP_ENV_VALIDATION: "true" <<: *turbo_env commands: - *use_deps - pnpm turbo lint --filter=@mosaic/orchestrator depends_on: - install typecheck: image: *node_image environment: SKIP_ENV_VALIDATION: "true" <<: *turbo_env commands: - *use_deps - pnpm turbo typecheck --filter=@mosaic/orchestrator depends_on: - install test: image: *node_image environment: SKIP_ENV_VALIDATION: "true" <<: *turbo_env commands: - *use_deps - pnpm turbo test --filter=@mosaic/orchestrator depends_on: - install # === Build === build: image: *node_image environment: SKIP_ENV_VALIDATION: "true" NODE_ENV: "production" <<: *turbo_env commands: - *use_deps - pnpm turbo build --filter=@mosaic/orchestrator depends_on: - lint - typecheck - test - security-audit # === Docker Build & Push === docker-build-orchestrator: image: gcr.io/kaniko-project/executor:debug environment: GITEA_USER: from_secret: gitea_username GITEA_TOKEN: from_secret: gitea_token CI_COMMIT_BRANCH: ${CI_COMMIT_BRANCH} CI_COMMIT_TAG: ${CI_COMMIT_TAG} commands: - *kaniko_setup - | DESTINATIONS="" if [ -n "$CI_COMMIT_TAG" ]; then DESTINATIONS="--destination git.mosaicstack.dev/mosaic/stack-orchestrator:$CI_COMMIT_TAG" elif [ "$CI_COMMIT_BRANCH" = "main" ]; then DESTINATIONS="--destination git.mosaicstack.dev/mosaic/stack-orchestrator:latest" fi /kaniko/executor --context . --dockerfile apps/orchestrator/Dockerfile --snapshot-mode=redo $DESTINATIONS when: - branch: [main] event: [push, manual, tag] depends_on: - build # === Container Security Scan === security-trivy-orchestrator: image: aquasec/trivy:latest environment: GITEA_USER: from_secret: gitea_username GITEA_TOKEN: from_secret: gitea_token CI_COMMIT_BRANCH: ${CI_COMMIT_BRANCH} CI_COMMIT_TAG: ${CI_COMMIT_TAG} commands: - | if [ -n "$$CI_COMMIT_TAG" ]; then SCAN_TAG="$$CI_COMMIT_TAG" elif [ "$$CI_COMMIT_BRANCH" = "main" ]; then SCAN_TAG="latest" else SCAN_TAG="latest" fi mkdir -p ~/.docker echo "{\"auths\":{\"git.mosaicstack.dev\":{\"username\":\"$$GITEA_USER\",\"password\":\"$$GITEA_TOKEN\"}}}" > ~/.docker/config.json trivy image --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed \ --ignorefile .trivyignore \ git.mosaicstack.dev/mosaic/stack-orchestrator:$$SCAN_TAG when: - branch: [main] event: [push, manual, tag] depends_on: - docker-build-orchestrator # === Package Linking === link-packages: image: alpine:3 environment: GITEA_TOKEN: from_secret: gitea_token commands: - apk add --no-cache curl - sleep 10 - | set -e link_package() { PKG="$$1" echo "Linking $$PKG..." for attempt in 1 2 3; do STATUS=$$(curl -s -o /tmp/link-response.txt -w "%{http_code}" -X POST \ -H "Authorization: token $$GITEA_TOKEN" \ "https://git.mosaicstack.dev/api/v1/packages/mosaic/container/$$PKG/-/link/stack") if [ "$$STATUS" = "201" ] || [ "$$STATUS" = "204" ]; then echo " Linked $$PKG" return 0 elif [ "$$STATUS" = "400" ]; then echo " $$PKG already linked" return 0 elif [ "$$STATUS" = "404" ] && [ $$attempt -lt 3 ]; then echo " $$PKG not found yet, retrying in 5s (attempt $$attempt/3)..." sleep 5 else echo " FAILED: $$PKG status $$STATUS" cat /tmp/link-response.txt return 1 fi done } link_package "stack-orchestrator" when: - branch: [main] event: [push, manual, tag] depends_on: - security-trivy-orchestrator