name: Deploy to OpenShift # GitOps 저장소와 ArgoCD Application이 아직 없어 CD를 push 방식으로 돌린다. # 파이프라인이 클러스터에 직접 helm upgrade를 건다. # # 이 방식의 대가를 숨기지 않는다. # - 클러스터의 실제 상태가 저장소와 자동으로 맞춰지지 않는다. 누가 oc edit으로 고치면 그대로 남는다. # - 배포 이력이 Helm release history에만 남는다. git revert로 되돌릴 수 없다. # - 파이프라인이 클러스터 자격증명을 들고 있어야 한다. # # 그래서 자동 트리거를 두지 않고 사람이 값을 확인하고 실행한다. # GitOps 저장소가 준비되면 이 워크플로를 삭제하고, ArgoCD Application이 이 Chart를 당겨 가게 한다. # 그때까지의 인수인계 형태는 CI가 올리는 rendered-manifests 아티팩트다. on: workflow_dispatch: inputs: environment: description: 배포 환경 (dev | test | prod) required: true default: dev mode: description: 배포 모델 (portal | bundles) required: true default: portal deploymentKey: description: mode=bundles일 때 설치할 배포 key. portal이면 비워 둔다 required: false default: "" imageTag: description: 배포할 이미지 tag. CI가 push한 commit sha를 그대로 넣는다 required: true env: HELM_IMAGE: alpine/helm:3.14.4 jobs: deploy: runs-on: ubuntu steps: - uses: actions/checkout@v4 - name: Deploy env: ENVIRONMENT: ${{ github.event.inputs.environment }} MODE: ${{ github.event.inputs.mode }} DEPLOYMENT_KEY: ${{ github.event.inputs.deploymentKey }} IMAGE_TAG: ${{ github.event.inputs.imageTag }} IMAGE_REPOSITORY: ${{ secrets.IMAGE_REPOSITORY }} OCP_SERVER: ${{ secrets.OCP_SERVER }} OCP_TOKEN: ${{ secrets.OCP_TOKEN }} # 사내 CA가 서명한 API 인증서일 때 PEM 전체를 넣는다. 비어 있으면 러너의 신뢰 저장소를 쓴다. OCP_CA_CERT: ${{ secrets.OCP_CA_CERT }} OCP_NAMESPACE_DEV: ${{ secrets.OCP_NAMESPACE_DEV }} OCP_NAMESPACE_TEST: ${{ secrets.OCP_NAMESPACE_TEST }} OCP_NAMESPACE_PROD: ${{ secrets.OCP_NAMESPACE_PROD }} run: | set -eu CA_FILE=.ocp-ca.crt trap 'rm -f "$CA_FILE"' EXIT case "$ENVIRONMENT" in dev) NAMESPACE=$OCP_NAMESPACE_DEV ;; test) NAMESPACE=$OCP_NAMESPACE_TEST ;; prod) NAMESPACE=$OCP_NAMESPACE_PROD ;; *) echo "environment는 dev|test|prod여야 한다: $ENVIRONMENT" >&2; exit 1 ;; esac for required in OCP_SERVER OCP_TOKEN IMAGE_REPOSITORY; do eval "value=\${$required}" if [ -z "$value" ]; then echo "$required secret이 없다. 플랫폼 담당자에게 발급받아 저장소 secret에 등록한다." >&2 exit 1 fi done if [ -z "$NAMESPACE" ]; then echo "$ENVIRONMENT namespace secret이 없다." >&2 exit 1 fi # release 이름은 mode가 정한다. portal은 배포가 하나이고, bundles는 배포 key마다 하나다. if [ "$MODE" = "portal" ]; then RELEASE=axhub-mcp EXTRA="" else if [ -z "$DEPLOYMENT_KEY" ]; then echo "mode=bundles에는 deploymentKey가 필요하다." >&2 exit 1 fi RELEASE="$DEPLOYMENT_KEY-mcp" EXTRA="--set deploymentKey=$DEPLOYMENT_KEY" fi # 사내 CA를 신뢰시키는 정상 경로다. TLS 검증을 끄는 스위치는 두지 않는다. if [ -n "$OCP_CA_CERT" ]; then printf '%s\n' "$OCP_CA_CERT" > "$CA_FILE" EXTRA="$EXTRA --kube-ca-file /workspace/$CA_FILE" fi # token은 helm 인자로 들어간다. 컨테이너는 명령마다 새로 뜨고 바로 사라지지만, # 러너를 여러 팀이 공유하게 되면 kubeconfig 파일 방식으로 바꾼다. # --atomic: 실패하면 직전 revision으로 되돌린다. 반쯤 배포된 상태로 두지 않는다. docker run --rm \ -v "$PWD":/workspace -w /workspace \ "$HELM_IMAGE" upgrade --install "$RELEASE" deploy/helm/mcp-server \ -f "deploy/helm/mcp-server/values-$ENVIRONMENT.yaml" \ --namespace "$NAMESPACE" \ --set "mode=$MODE" \ $EXTRA \ --set "image.repository=$IMAGE_REPOSITORY" \ --set "image.tag=$IMAGE_TAG" \ --kube-apiserver "$OCP_SERVER" \ --kube-token "$OCP_TOKEN" \ --atomic --timeout 10m