--- # ============================================================================= # Drone CI Pipeline # ============================================================================= kind: pipeline type: kubernetes name: default trigger: event: - push - tag branch: - main environment: REGISTRY: harbor.gitdata.me/gta_team CARGO_TERM_COLOR: always BUILD_TARGET: x86_64-unknown-linux-gnu steps: # ============================================================================= # Clone # ============================================================================= - name: clone image: bitnami/git:latest commands: - | if [ -n "${DRONE_TAG}" ]; then git checkout ${DRONE_TAG} fi # ============================================================================= # Stage 1: Rust – fmt + clippy + test # ============================================================================= - name: rust-fmt image: rust:1.94 commands: - cargo fmt --all -- --check - name: rust-clippy image: rust:1.94 commands: - apt-get update && apt-get install -y --no-install-recommends \ pkg-config libssl-dev libclang-dev libgit2-dev zlib1g-dev - rustup component add clippy - cargo clippy --workspace --all-targets -- -D warnings - name: rust-test image: rust:1.94 commands: - apt-get update && apt-get install -y --no-install-recommends \ pkg-config libssl-dev libclang-dev libgit2-dev zlib1g-dev - cargo test --workspace --all-features # ============================================================================= # Stage 2: Frontend – lint + typecheck + build # ============================================================================= - name: frontend-deps image: node:22-alpine commands: - corepack enable - corepack prepare pnpm@10 --activate - pnpm install --frozen-lockfile - name: frontend-lint image: node:22-alpine commands: - pnpm lint depends_on: [ frontend-deps ] - name: frontend-typecheck image: node:22-alpine commands: - pnpm tsc -b --noEmit depends_on: [ frontend-lint ] - name: frontend-build image: node:22-alpine commands: - pnpm build depends_on: [ frontend-typecheck ] # ============================================================================= # Stage 3: Docker build & push # ============================================================================= - name: docker-login image: docker:latest commands: - docker login ${REGISTRY} --username ${DRONE_SECRET_DOCKER_USERNAME} --password-stdin <<< ${DRONE_SECRET_DOCKER_PASSWORD} when: status: [ success ] - name: docker-build-and-push image: docker:latest environment: DOCKER_BUILDKIT: "1" commands: - | TAG="${DRONE_TAG:-${DRONE_COMMIT_SHA:0:8}}" echo "==> Building images with tag: ${TAG}" docker build --build-arg BUILD_TARGET=${BUILD_TARGET} -f docker/app.Dockerfile -t ${REGISTRY}/app:${TAG} . docker build --build-arg BUILD_TARGET=${BUILD_TARGET} -f docker/gitserver.Dockerfile -t ${REGISTRY}/gitserver:${TAG} . docker build --build-arg BUILD_TARGET=${BUILD_TARGET} -f docker/email-worker.Dockerfile -t ${REGISTRY}/email-worker:${TAG} . docker build --build-arg BUILD_TARGET=${BUILD_TARGET} -f docker/git-hook.Dockerfile -t ${REGISTRY}/git-hook:${TAG} . docker build --build-arg BUILD_TARGET=${BUILD_TARGET} -f docker/migrate.Dockerfile -t ${REGISTRY}/migrate:${TAG} . docker build --build-arg BUILD_TARGET=${BUILD_TARGET} -f docker/operator.Dockerfile -t ${REGISTRY}/operator:${TAG} . docker build -f docker/static.Dockerfile -t ${REGISTRY}/static:${TAG} . docker build -f docker/frontend.Dockerfile -t ${REGISTRY}/frontend:${TAG} . echo "==> Pushing images" for svc in app gitserver email-worker git-hook migrate operator static frontend; do docker push ${REGISTRY}/${svc}:${TAG} done echo "==> Tagging as latest" for svc in app gitserver email-worker git-hook migrate operator static frontend; do docker tag ${REGISTRY}/${svc}:${TAG} ${REGISTRY}/${svc}:latest docker push ${REGISTRY}/${svc}:latest done echo "==> All images pushed" depends_on: [ docker-login, frontend-build ] settings: privileged: true when: status: [ success ] # ============================================================================= # Stage 4: Deploy to Kubernetes # ============================================================================= - name: prepare-kubeconfig image: alpine:latest commands: - apk add --no-cache kubectl - mkdir -p ~/.kube - echo "${KUBECONFIG}" | base64 -d > ~/.kube/config - chmod 600 ~/.kube/config - name: create-namespace image: bitnami/kubectl:latest commands: - kubectl create namespace gitdataai --dry-run=client -o yaml | kubectl apply -f - depends_on: [ prepare-kubeconfig ] when: branch: [ main ] - name: deploy-configmap image: bitnami/kubectl:latest commands: - kubectl apply -f deploy/configmap.yaml depends_on: [ create-namespace ] when: branch: [ main ] - name: helm-deploy image: alpine/helm:latest commands: - apk add --no-cache curl kubectl - curl -fsSL -o /tmp/helm.tar.gz https://get.helm.sh/helm-v3.15.0-linux-amd64.tar.gz - tar -xzf /tmp/helm.tar.gz -C /tmp - mv /tmp/linux-amd64/helm /usr/local/bin/helm && chmod +x /usr/local/bin/helm - | TAG="${DRONE_TAG:-${DRONE_COMMIT_SHA:0:8}}" helm upgrade --install gitdata deploy/ \ --namespace gitdataai \ -f deploy/values.yaml \ -f deploy/secrets.yaml \ --set image.registry=${REGISTRY} \ --set app.image.tag=${TAG} \ --set gitserver.image.tag=${TAG} \ --set emailWorker.image.tag=${TAG} \ --set gitHook.image.tag=${TAG} \ --set operator.image.tag=${TAG} \ --set static.image.tag=${TAG} \ --set frontend.image.tag=${TAG} \ --wait \ --timeout 5m \ --atomic depends_on: [ deploy-configmap ] when: status: [ success ] branch: [ main ] - name: verify-rollout image: bitnami/kubectl:latest commands: - kubectl rollout status deployment/gitdata-frontend -n gitdataai --timeout=300s - kubectl rollout status deployment/gitdata-app -n gitdataai --timeout=300s - kubectl rollout status deployment/gitdata-gitserver -n gitdataai --timeout=300s - kubectl rollout status deployment/gitdata-email-worker -n gitdataai --timeout=300s - kubectl rollout status deployment/gitdata-git-hook -n gitdataai --timeout=300s depends_on: [ helm-deploy ] when: status: [ success ] branch: [ main ] # ============================================================================= # Secrets (register via drone CLI) # # # Harbor username for docker login # drone secret add \ # --repository \ # --name drone_secret_docker_username \ # --data # # # Harbor password for docker login # drone secret add \ # --repository \ # --name drone_secret_docker_password \ # --data # # # kubeconfig (base64 encoded) # drone secret add \ # --repository \ # --name kubeconfig \ # --data "$(cat ~/.kube/config | base64 -w 0)" # # # Local exec (for testing): # drone exec --trusted \ # --secret=DRONE_SECRET_DOCKER_USERNAME= \ # --secret=DRONE_SECRET_DOCKER_PASSWORD= \ # --secret=KUBECONFIG=$(base64 -w 0 ~/.kube/config) # =============================================================================