appsok/agent-roadmap/archive/phase/workflow-integration/milestones/macos-build-ci.md

8 KiB

Milestone: macOS 빌드 CI와 인증 빌드

위치

  • Roadmap: agent-roadmap/ROADMAP.md
  • Phase: agent-roadmap/phase/workflow-integration/PHASE.md

목표

Teams deep link와 설치 이력 작업으로 들어가기 전에, 원격 Mac runner에서 AppSok macOS 빌드가 재현 가능하게 생성되고 최종 배포 후보가 Developer ID signing, notarization, stapling까지 통과하는지 확인한다. 생성된 인증 빌드는 다음 업무 흐름 Milestone의 검증 출발점으로 재사용할 수 있어야 한다.

상태

[완료]

승격 조건

  • 없음

구현 잠금

  • 상태: 해제
  • 결정 필요: 없음

범위

  • remote Mac runner의 Flutter/Xcode/codesigning readiness 확인
  • flutter analyze, flutter test, flutter build macos를 CI 후보 명령으로 정리
  • macOS release .app bundle 생성 여부 확인
  • Developer ID signing, notarization, stapling, Gatekeeper assessment 확인
  • MDM 배포 정책과 조직 배포 자동화는 후속 배포 Milestone과 분리

기능

Epic: [baseline] 원격 Mac 빌드 baseline

원격 Mac runner에서 현재 checkout을 실제로 빌드할 수 있는지 확인한다.

  • [remote-env] remote checkout, Flutter, Xcode, codesigning identity 상태를 확인한다.
  • [analyze-test] remote runner에서 flutter analyzeflutter test를 통과시킨다.
  • [macos-build] remote runner에서 flutter build macosRelease/AppSok.app을 생성한다.
  • [bundle-check] 빌드 산출물의 앱 이름, bundle id, codesign 상태를 확인한다.

Epic: [ci] CI 게이트 정의

반복 가능한 CI 검증으로 만들기 위해 명령, runner, 산출물, 실패 기준을 문서화한다.

  • [ci-commands] CI에서 실행할 명령 순서와 기대 출력을 정리한다.
  • [runner-contract] remote Mac runner 또는 self-hosted runner 필수 조건을 정리한다.
  • [artifact-output] AppSok.app 산출물 경로, 보존 방식, build evidence 위치를 정한다.
  • [signing-boundary] adhoc build, Developer ID signing, notarization의 책임 경계를 기록한다.

Epic: [certified] 최종 인증 빌드

최종 배포 후보를 macOS Gatekeeper 기준으로 검증 가능한 상태로 만든다.

  • [keychain-access] 비대화식 CI 세션에서 Developer ID private key 접근이 가능한지 확인한다.
  • [developer-id-sign] AppSok.app과 nested framework/runtime 파일을 Developer ID로 서명한다.
  • [notary-submit] notarytool submit --wait로 Apple notarization을 통과시킨다.
  • [staple] notarization ticket을 산출물에 staple한다.
  • [gatekeeper] spctl --assess --verbose로 배포 후보 실행 가능성을 확인한다.
  • [certified-artifact] 인증된 산출물 경로와 checksum을 기록한다.

완료 리뷰

  • 상태: 승인됨
  • 요청일: 2026-06-14
  • 완료 근거:
    • 원격 Mac runner에서 Flutter/Xcode/codesigning readiness, flutter analyze, flutter test, flutter build macos를 통과했다.
    • Developer ID signing, Apple notarization, stapling, Gatekeeper assessment, 최종 ZIP checksum 기록을 완료했다.
    • SOPS secret setup과 인증 빌드 반복 실행 절차를 스크립트, 문서, 테스트로 남겼다.
  • 리뷰 필요:
    • 사용자가 완료 결과를 확인했다
    • archive 이동을 승인했다
  • 리뷰 코멘트: 전체화면 전용 검증은 제품 목표가 아니므로 완료 조건에서 제외한다. 일반 창 기반 업무 흐름 확인은 각 후속 기능 Milestone의 smoke에서 필요할 때 다룬다.

범위 제외

  • Teams deep link 구현
  • 전체화면 전용 UX 또는 전체화면 모드 검증
  • 실제 Jenkins credential 또는 private endpoint 원문 기록
  • 조직 배포 채널과 MDM 자동화 정책 확정

작업 컨텍스트

  • 관련 경로: macos/, pubspec.yaml, CI 설정 후보 파일
  • 관련 문서: docs/macos-certified-build.md, agent-test/local/macos-remote-build-smoke.md
  • 관련 테스트: test/certified_macos_scripts_test.dart
  • 표준선(선택): CI baseline은 flutter pub get, flutter analyze, flutter test, flutter build macos 순서로 둔다.
  • 표준선(선택): 인증서 원문, private key, password, Apple account secret은 채팅/roadmap/tracked 파일에 기록하지 않고 runner Keychain 또는 CI secret으로만 다룬다.
  • 표준선(선택): adhoc build, Developer ID signing, notarization은 서로 다른 검증 단계로 기록하고, 인증 빌드는 scripts/build-certified-macos.sh로 반복한다.
  • 검증 메모:
    • 2026-06-14 remote checkout: main...origin/main, clean.
    • flutter --version --machine: Flutter 3.44.0, Dart 3.12.0.
    • xcodebuild -version: Xcode 26.0.1, Build 17A400.
    • security find-identity -v -p codesigning: valid identity 3개 확인.
    • flutter pub get PASS.
    • flutter analyze PASS: No issues found!.
    • flutter test PASS: 215: All tests passed!.
    • flutter build macos PASS: Built build/macos/Build/Products/Release/AppSok.app (60.2MB).
    • Bundle check: 앱 이름 AppSok, bundle id com.tokilabs.appsok, codesign Signature=adhoc, universal x86_64 arm64.
    • 2026-06-14 signing readiness check: notarytool version 1.1.0 (39) 확인.
    • 2026-06-14 signing blocker: SSH 비대화식 세션에서 security show-keychain-info login.keychain-dbUser interaction is not allowed로 실패했고, notary profile 조회는 keychainLocked에서 중단됐다.
    • 2026-06-14 signing blocker: Developer ID로 임시 executable 서명 probe와 AppSok.app 서명 시도가 errSecInternalComponent로 실패했다. 인증서 원문 문제가 아니라 runner Keychain/private key 접근 준비가 필요한 상태다.
    • 2026-06-14 secret manager check: remote runner에는 sops 3.13.1age가 설치되어 있다. AppSok repo 안에는 아직 .sops.yaml 또는 AppSok용 encrypted secret 파일이 없고, SSH 세션에 SOPS_AGE_KEY_FILE도 설정되어 있지 않아 현재 CI secret retrieval 경로로 바로 사용할 수는 없다.
    • 2026-06-14 secret manager setup: scripts/setup-appsok-ci-secrets.sh로 SOPS encrypted secret file secrets/appsok.ci.sops.json, age key $HOME/.config/sops/age/appsok-ci-key.txt, notary profile appsok-notary를 준비했다.
    • 2026-06-14 signing readiness resolved: SOPS 복호화, keychain unlock, appsok-notary profile 접근, Developer ID signing probe가 통과했다.
    • 2026-06-14 certified build first attempt: AppSok.app 본체는 Developer ID 서명됐으나 Contents/Resources/adb-runtime/adb가 resource executable로 남아 notarization Invalid 처리됐다. submission id: 57457c8f-9b0b-4e6f-a387-760ce98279c0.
    • 2026-06-14 certified build success: bundled adb를 먼저 Developer ID + hardened runtime + timestamp로 서명한 뒤 AppSok.app을 서명했고 notarization Accepted, stapler worked, spctl source=Notarized Developer ID를 확인했다. submission id: eda0f701-78f4-45b5-91ce-58e49b0b7000.
    • 2026-06-14 certified artifact: build/macos/Build/Products/Release/AppSok-certified.zip, size 23M, sha256 1c8e89816d4cbf92bcf7c70aa40a4e36ae29efeaeb3cc64ce391c22bc6deef2a.
    • 반복 실행 명령: scripts/build-certified-macos.sh.
    • 2026-06-14 docs/test: docs/macos-certified-build.mdtest/certified_macos_scripts_test.dart를 추가해 secret setup, certified build command, bundled adb signing 순서, notarization/stapling/Gatekeeper 기준을 남겼다.
    • 2026-06-14 verification: flutter test test/certified_macos_scripts_test.dart PASS, flutter analyze PASS, git diff --check PASS.
    • 2026-06-14 code-level closure review: APPSOK_CI_SECRET_FILE override 시 .sops.yaml creation rule이 기본 경로에 고정되는 작은 이슈를 수정했고, bash -n scripts/setup-appsok-ci-secrets.sh scripts/build-certified-macos.sh, flutter test, flutter analyze, git diff --check PASS.
  • 선행 작업: ADB 콘솔과 logcat
  • 후속 작업: Teams deep link 설치 진입
  • 확인 필요: 사용자 완료 확인과 archive 이동 승인.