stages: - check - test - package - release variables: NODE_VERSION: "20" PYTHON_VERSION: "3.11" OLLAMA_VERSION: "v0.5.7" npm_config_cache: "$CI_PROJECT_DIR/.npm" .node-cache: &node-cache cache: key: files: - package-lock.json paths: - .npm/ - node_modules/ # ──────────────────────────────────────────────────────────────────── # Docker 기반 검증 잡 — TW-BUILD01(build-linux-x64) Docker runner에서 실행. # 현재 manual 유지 (모노레포 docker 빌드 미검증). 안정화되면 auto로 복원. # ──────────────────────────────────────────────────────────────────── lint: stage: check image: node:${NODE_VERSION} tags: - build-linux-x64 <<: *node-cache before_script: - npm ci --ignore-scripts script: - npm run lint rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" when: manual allow_failure: true - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: manual allow_failure: true typecheck: stage: check image: node:${NODE_VERSION} tags: - build-linux-x64 <<: *node-cache before_script: - npm ci --ignore-scripts script: - npm run typecheck rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" when: manual allow_failure: true - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: manual allow_failure: true unit-test: stage: test image: node:${NODE_VERSION} tags: - build-linux-x64 <<: *node-cache before_script: - npm ci --ignore-scripts script: - npm run test:unit rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" when: manual allow_failure: true - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: manual allow_failure: true # ──────────────────────────────────────────────────────────────────── # Package Windows — 태그 푸시(v*) 또는 default 브랜치 수동 트리거 시 실행. # self-hosted Windows runner (shell executor, powershell shell) 필요. # 이 PC의 Node/Python/npm을 그대로 사용. # ──────────────────────────────────────────────────────────────────── package-windows: stage: package tags: - build-win-x64 before_script: - node --version - python --version - npm ci script: # 0) 태그 → package.json 버전 동기화 (설치파일명/latest.yml 일치) - node scripts/ci/sync-version.mjs # 1) Python sidecar 의존성 + PyInstaller 빌드 - python -m pip install --upgrade pip - python -m pip install pyinstaller - python -m pip install -r apps/desktop/sidecar/requirements.txt - python apps/desktop/scripts/build-sidecar.py # 2) SoX 다운로드 - powershell -ExecutionPolicy Bypass -File apps/desktop/scripts/download-sox.ps1 # 3) Ollama 다운로드 - powershell -ExecutionPolicy Bypass -File apps/desktop/scripts/download-ollama.ps1 # 4) electron-vite 빌드 + electron-builder NSIS 패키징 - npm run build --workspace=@d3ro/desktop - npm run dist:win --workspace=@d3ro/desktop artifacts: name: "d3ro-voice-windows-${CI_COMMIT_SHORT_SHA}" # win-unpacked/ (수GB)은 제외하고 최종 .exe 설치파일 + 메타만 업로드. # expose_as는 와일드카드와 병행 불가라 제거. Artifacts 링크는 Job 페이지에서 접근. paths: - apps/desktop/release/*/*.exe # latest.yml — detectUpdateChannel:false로 채널 고정. *.yml로 방어적 매치. - apps/desktop/release/*/*.yml - apps/desktop/release/*/*.blockmap expire_in: 90 days rules: - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+/ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: manual allow_failure: true # ──────────────────────────────────────────────────────────────────── # Package macOS — arm64 무서명 dmg+zip. (agent-switchboard 파이프라인 패턴 이식) # self-hosted mac runner (shell executor, tags: macos+arm64) 필요. # 전제: brew install sox, Xcode CLT, Python 3.11+. # 서명/공증은 후속 단계 (현재 notarize:false — 사용자는 우클릭→열기로 실행). # ──────────────────────────────────────────────────────────────────── package-macos: stage: package tags: - build-mac-arm64 before_script: # CI 셸은 로그인 셸이 아니라 brew/volta가 PATH에 없음 — 명시적으로 추가 - export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" - export VOLTA_HOME="${VOLTA_HOME:-$HOME/.volta}" - export PATH="$VOLTA_HOME/bin:$PATH" - command -v volta >/dev/null 2>&1 && volta install node@22 || true # 무서명(ad-hoc) 빌드 강제 — runner에 인증서가 있어도 집어쓰지 않게 차단 # (agent-switchboard의 dist:mac:unsigned 검증된 조합) - export CSC_IDENTITY_AUTO_DISCOVERY=false - node --version - python3 --version - npm ci script: # 0) 태그 → package.json 버전 동기화 - node scripts/ci/sync-version.mjs # 1) Python sidecar — PEP 668(externally-managed) 회피를 위해 venv 사용 - python3 -m venv apps/desktop/sidecar/.venv-ci - apps/desktop/sidecar/.venv-ci/bin/pip install --upgrade pip - apps/desktop/sidecar/.venv-ci/bin/pip install pyinstaller - apps/desktop/sidecar/.venv-ci/bin/pip install -r apps/desktop/sidecar/requirements.txt - apps/desktop/sidecar/.venv-ci/bin/python apps/desktop/scripts/build-sidecar.py # 2) SoX 번들 (brew sox → resources/sox/ 복사 + dylib rpath 재배치) # runner에 sox 미설치면 user-level brew로 설치 (idempotent) - command -v sox >/dev/null 2>&1 || brew install sox - bash apps/desktop/scripts/install-sox.sh # 3) Ollama 다운로드 (darwin tgz) - bash apps/desktop/scripts/download-ollama.sh # 4) electron-vite 빌드 + electron-builder dmg/zip (arm64) - npm run dist:mac --workspace=@d3ro/desktop artifacts: name: "d3ro-voice-macos-${CI_COMMIT_SHORT_SHA}" paths: - apps/desktop/release/*/*.dmg - apps/desktop/release/*/*.zip - apps/desktop/release/*/*.yml - apps/desktop/release/*/*.blockmap expire_in: 90 days rules: # mac runner 등록 후 프로젝트 CI/CD 변수 D3RO_MAC_RUNNER="true" 설정 시에만 실행. # 변수 미설정 시 잡이 생성되지 않아(release-create의 optional needs) 릴리스가 막히지 않는다. # allow_failure: mac 잡이 실패해도(needs가 성공 취급) Windows 단독 릴리스로 진행. - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+/ && $D3RO_MAC_RUNNER == "true" allow_failure: true - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $D3RO_MAC_RUNNER == "true" when: manual allow_failure: true # ──────────────────────────────────────────────────────────────────── # Release — artifacts를 Generic Package Registry(버전별 + latest)에 업로드하고 # GitLab Release + asset 링크를 생성. (agent-switchboard 패턴 이식) # latest 패키지 경로는 electron-updater feed로 사용된다. # macOS artifacts는 optional — mac runner 미등록/실패 시 Windows 단독 릴리스. # ──────────────────────────────────────────────────────────────────── release-create: stage: release image: node:22-bookworm tags: - build-linux-x64 needs: - job: package-windows artifacts: true - job: package-macos artifacts: true optional: true resource_group: d3ro-voice-release script: - node scripts/ci/publish-gitlab-release.mjs rules: - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+/