From b4400065a2db6736362736a220fc7494168cd54b Mon Sep 17 00:00:00 2001 From: toki Date: Sun, 14 Jun 2026 20:41:16 +0900 Subject: [PATCH] update domain rules and workflow integration roadmap --- .../rules/project/domain/app-shell/rules.md | 17 +++++++---- .../project/domain/artifact-flow/rules.md | 28 ++++++++++++++----- .../project/domain/device-console/rules.md | 23 ++++++++++----- .../project/domain/macos-platform/rules.md | 26 +++++++++++++---- agent-ops/rules/project/rules.md | 5 ++-- .../milestones/macos-build-ci.md | 9 +++--- .../phase/workflow-integration/PHASE.md | 6 ++-- .../milestones/teams-deep-link.md | 3 +- scripts/setup-appsok-ci-secrets.sh | 22 ++++++--------- test/certified_macos_scripts_test.dart | 7 ++++- 10 files changed, 97 insertions(+), 49 deletions(-) rename agent-roadmap/{ => archive}/phase/workflow-integration/milestones/macos-build-ci.md (94%) diff --git a/agent-ops/rules/project/domain/app-shell/rules.md b/agent-ops/rules/project/domain/app-shell/rules.md index c0e8099..b958813 100644 --- a/agent-ops/rules/project/domain/app-shell/rules.md +++ b/agent-ops/rules/project/domain/app-shell/rules.md @@ -1,32 +1,35 @@ --- domain: app-shell -last_rule_review_commit: no-commit -last_rule_updated_at: 2026-06-08 +last_rule_review_commit: c1c4c41886f44727ad5b9297ec164198d1dd5bd9 +last_rule_updated_at: 2026-06-14 --- # app-shell ## 목적 / 책임 -AppSok의 전역 앱 구성, 기본 navigation shell, theme, 화면 간 진입 구조를 담당한다. +AppSok의 전역 앱 구성, startup session restore wiring, navigation shell, theme, feature 간 진입/상태 전달을 담당한다. ## 포함 경로 - `lib/main.dart` — Flutter 앱 실행 진입점 - `lib/src/app.dart` — `MaterialApp`과 전역 theme 연결 - `lib/src/features/app_shell.dart` — 빌드/디바이스/콘솔/설정 navigation shell +- `lib/src/models/pending_install.dart` — artifact-flow와 device-console 사이의 설치 대기 handoff 모델 - `lib/src/theme/` — 앱 전역 색상, typography, component theme ## 제외 경로 - `lib/src/features/builds/` — Jenkins artifact 조회/설치 흐름은 `artifact-flow` 책임 - `lib/src/features/devices/`, `lib/src/features/console/` — ADB device/logcat 흐름은 `device-console` 책임 +- `lib/src/services/**` — 외부 연동과 runtime semantics는 각 service 소유 도메인 책임 - `macos/` — bundle, entitlement, URL scheme은 `macos-platform` 책임 ## 주요 구성 요소 - `AppSokApp` — 앱 루트 widget -- `AppSokShell` — 좌측 navigation과 상단 상태 영역 +- `AppSokShell` — 좌측 navigation, 상단 상태 영역, feature 간 설치 대기 상태 전달 +- `PendingInstall` — staged APK를 device-console에 넘기는 cross-feature DTO - `AppTheme` — AppSok Material 3 light theme ## 유지할 패턴 @@ -34,13 +37,15 @@ AppSok의 전역 앱 구성, 기본 navigation shell, theme, 화면 간 진입 - 첫 화면은 실제 업무 화면이어야 하며 landing/marketing 화면으로 만들지 않는다. - 사용자 표시명은 `AppSok`으로 통일한다. Dart package, URL scheme, bundle id처럼 소문자 식별자가 필요한 곳만 `appsok`을 유지한다. - navigation item 추가 시 domain 경계를 먼저 정하고, shell에는 route/entry wiring만 둔다. +- shell은 Jenkins session, artifact staging, ADB loader/installer 같은 dependency를 주입·연결하되 실제 외부 호출 semantics는 service 도메인에 둔다. +- 설치 대기 상태와 staged file cleanup은 페이지 dispose에 끊기지 않도록 shell에서 소유한다. - 버튼과 상태 표시는 icon을 우선 사용하고, 긴 설명성 문구는 화면 안에 넣지 않는다. - 카드 반경은 8px 이하를 유지한다. ## 다른 도메인과의 경계 -- **artifact-flow**: Jenkins 인증/빌드 목록 상태는 artifact-flow가 소유하고, shell은 연결 상태 요약만 표시한다. -- **device-console**: ADB 연결 상태 원천은 device-console이 소유하고, shell은 요약만 표시한다. +- **artifact-flow**: Jenkins 인증/빌드 목록/다운로드/staged APK 생성은 artifact-flow가 소유하고, shell은 loader와 install handoff만 연결한다. +- **device-console**: ADB 연결 상태, 설치 실행, logcat session은 device-console이 소유하고, shell은 device 선택과 pending install 전달만 조율한다. - **macos-platform**: 앱 이름, URL scheme, entitlement 변경은 platform 설정에서 처리한다. ## 금지 사항 diff --git a/agent-ops/rules/project/domain/artifact-flow/rules.md b/agent-ops/rules/project/domain/artifact-flow/rules.md index 730f593..16c9af4 100644 --- a/agent-ops/rules/project/domain/artifact-flow/rules.md +++ b/agent-ops/rules/project/domain/artifact-flow/rules.md @@ -1,14 +1,14 @@ --- domain: artifact-flow -last_rule_review_commit: no-commit -last_rule_updated_at: 2026-06-08 +last_rule_review_commit: c1c4c41886f44727ad5b9297ec164198d1dd5bd9 +last_rule_updated_at: 2026-06-14 --- # artifact-flow ## 목적 / 책임 -Jenkins 인증, build 목록 조회, artifact 선택/다운로드, 설치 요청 직전까지의 흐름을 담당한다. +Jenkins 인증, Web Login token 발급 bridge, session restore, job/build/artifact 조회, 다운로드 stream, APK staging/검증/cleanup, 설치 handoff 직전까지의 흐름을 담당한다. ## 포함 경로 @@ -16,32 +16,45 @@ Jenkins 인증, build 목록 조회, artifact 선택/다운로드, 설치 요청 - `lib/src/features/settings/` — Jenkins base URL, job, 인증 방식 설정 UI - `lib/src/models/jenkins_build.dart` — Jenkins build/artifact 모델 - `lib/src/services/jenkins_client.dart` — Jenkins Remote API 호출 +- `lib/src/services/jenkins_artifact_session.dart` — 저장된 Jenkins session 복원과 조회/다운로드/staging facade +- `lib/src/services/artifact_staging_service.dart` — 다운로드된 APK 임시 staging, 검증, cleanup - `lib/src/services/token_store.dart` — 사용자별 Jenkins credential 저장 ## 제외 경로 - `lib/src/services/adb_service.dart` — 실제 설치 실행은 `device-console` 책임 - `lib/src/features/devices/`, `lib/src/features/console/` — 연결 기기와 logcat UI는 `device-console` 책임 +- `lib/src/models/pending_install.dart` — staged APK를 device-console으로 넘기는 handoff DTO는 `app-shell` 책임 - `macos/Runner/` — Keychain, network entitlement, URL scheme은 `macos-platform` 책임 ## 주요 구성 요소 - `BuildsPage` — Jenkins build/artifact 탐색 화면 -- `JenkinsBuild`, `BuildArtifact` — build와 artifact 도메인 모델 +- `SettingsPage`, `JenkinsWebLoginPage` — Jenkins URL 입력, Web Login, token 저장/clear UI와 injected ADB 진단 표시 surface +- `JenkinsJob`, `JenkinsBuild`, `BuildArtifact` — job, build, artifact 도메인 모델 - `JenkinsClient` — build 조회와 artifact 다운로드 HTTP client -- `TokenStore` — macOS Keychain credential 저장소 wrapper +- `DownloadTask`, `DownloadProgressEvent` — artifact 다운로드 stream과 취소 가능한 progress 이벤트 +- `JenkinsArtifactSession`, `JenkinsSessionRestoreResult` — credential 복원, 권한 확인, 조회/다운로드/staging orchestration +- `ArtifactStagingService`, `StagedApk`, `ArtifactVerifyException` — APK staging, 확장자/크기 검증, cleanup +- `TokenStore`, `JenkinsSessionConfig` — macOS Keychain credential/session 저장소 wrapper +- `JenkinsCrumb`, `JenkinsGeneratedToken`, `JenkinsBridgeTokenResult` — Jenkins Web Login token bridge parsing 모델 ## 유지할 패턴 - Jenkins credential은 사용자별로 저장하고, tracked 파일이나 앱 bundle에 secret을 넣지 않는다. - Jenkins API 응답 parsing은 모델 factory 또는 전용 parser에 둔다. +- Jenkins URL path 조합은 context path를 보존하는 helper를 사용하고, 문자열 덧붙이기로 login/API 경로를 만들지 않는다. +- WebView token bridge는 same-origin fetch로 `whoAmI`, crumb, token 발급 응답을 확인하고, token 이름에는 secret을 넣지 않는다. +- `DownloadProgressEvent`는 누적 byte와 chunk byte를 함께 전달하고, 취소 시 stream을 닫아 partial staging이 남지 않게 한다. +- staging된 파일은 `.apk` 확장자와 non-empty 조건을 검증하고, 취소/오류/설치 완료/대기 취소 시 cleanup 경로를 유지한다. +- session 저장은 저장 직후 restore 검증까지 성공했을 때만 완료로 보고, 실패하면 저장값을 rollback한다. - 다운로드 파일명과 build number, job, flavor, branch를 UI에서 함께 노출해 오설치 가능성을 낮춘다. - Jenkins WebView 자동 token 발급을 구현할 때도 LDAP 비밀번호 원문을 앱 상태나 로그에 남기지 않는다. ## 다른 도메인과의 경계 -- **device-console**: artifact-flow는 설치할 파일과 대상 요청만 넘기고, `adb install` 실행과 logcat 처리는 device-console에서 담당한다. -- **app-shell**: 로그인/동기화 상태 summary만 shell에 전달하고, 상세 상태와 오류는 artifact-flow 화면에서 관리한다. +- **device-console**: artifact-flow는 staged APK와 build/artifact metadata까지만 만들고, `adb install`, logcat, ADB 진단 타입/loader semantics는 device-console에서 담당한다. +- **app-shell**: 로그인/동기화 상태, loader, staged APK handoff만 shell에 전달하고, 상세 상태와 오류는 artifact-flow 화면/서비스에서 관리한다. - **macos-platform**: 인증 callback deep link, sandbox/network 권한은 macos-platform과 함께 변경한다. ## 금지 사항 @@ -49,3 +62,4 @@ Jenkins 인증, build 목록 조회, artifact 선택/다운로드, 설치 요청 - 공용 Jenkins API token, service account token을 소스/설정/README에 기록하지 않는다. - Jenkins 권한 확인을 단순 boolean 로그인 상태만으로 대체하지 않는다. - artifact URL을 외부 네트워크에 노출하거나 로그에 token 포함 URL을 출력하지 않는다. +- staged APK를 tracked 경로에 쓰거나 cleanup 없는 장기 캐시로 전환하지 않는다. diff --git a/agent-ops/rules/project/domain/device-console/rules.md b/agent-ops/rules/project/domain/device-console/rules.md index db8da92..adcdb0d 100644 --- a/agent-ops/rules/project/domain/device-console/rules.md +++ b/agent-ops/rules/project/domain/device-console/rules.md @@ -1,14 +1,14 @@ --- domain: device-console -last_rule_review_commit: no-commit -last_rule_updated_at: 2026-06-08 +last_rule_review_commit: c1c4c41886f44727ad5b9297ec164198d1dd5bd9 +last_rule_updated_at: 2026-06-14 --- # device-console ## 목적 / 책임 -USB로 연결된 Android 기기 조회, APK 설치, logcat/ADB 콘솔 경험을 담당한다. +USB로 연결된 Android 기기 조회, APK 설치, ADB runtime 해석/진단, logcat/ADB 콘솔 경험을 담당한다. ## 포함 경로 @@ -21,6 +21,7 @@ USB로 연결된 Android 기기 조회, APK 설치, logcat/ADB 콘솔 경험을 - `lib/src/services/jenkins_client.dart` — Jenkins API 호출은 `artifact-flow` 책임 - `lib/src/features/builds/` — artifact 선택과 다운로드는 `artifact-flow` 책임 +- `lib/src/models/pending_install.dart` — 설치 대기 handoff DTO는 `app-shell` 책임이며 device-console은 입력으로만 소비 - `macos/` — sandbox, process 실행, USB 접근 정책은 `macos-platform` 책임 ## 주요 구성 요소 @@ -29,22 +30,30 @@ USB로 연결된 Android 기기 조회, APK 설치, logcat/ADB 콘솔 경험을 - `ConsolePage` — logcat console UI - `AdbDevice` — serial/state/model/product metadata - `AdbService` — ADB command 실행 wrapper +- `AdbRuntimeConfig`, `AdbRuntime` — bundled/custom/system ADB 선택과 `ADB_SERVER_PORT` 환경 구성 +- `AdbLogcatSession` — running `adb logcat` process lifetime wrapper +- `AdbRuntimeDiagnostics` — ADB executable path/source/version/SHA-256 진단 결과 +- `AdbInstallResult`, `AdbException` — 설치 결과와 ADB 오류 표현 ## 유지할 패턴 - 화면 코드에서 `Process.run` 또는 `Process.start`를 직접 호출하지 않고 `AdbService`를 통한다. +- ADB runtime 선택은 custom path, bundled path, system fallback 순서를 유지하고, 기본 AppSok 전용 server port는 `5038`로 둔다. - `adb devices -l` parsing은 다양한 state(`device`, `unauthorized`, `offline`)를 허용한다. - 설치 결과는 exit code, stdout, stderr를 모두 보존해 사용자에게 원인 파악 정보를 제공한다. -- logcat stream은 pause/clear/filter 같은 UI 상태와 process lifetime을 분리해 설계한다. +- logcat stream은 pause/clear/filter 같은 UI 상태와 process lifetime을 분리하고, `AdbLogcatSession.stop`으로 process를 종료한다. +- 콘솔 UI는 오래 실행되는 logcat session에서 화면 보관 line 수를 제한하고 level/text filter를 UI 상태로만 관리한다. +- ADB 진단은 `adb version` timeout과 executable SHA-256 계산을 best-effort로 수행한다. ## 다른 도메인과의 경계 -- **artifact-flow**: 설치할 APK 경로만 입력으로 받고 Jenkins 인증/다운로드 상태에는 의존하지 않는다. -- **app-shell**: 연결된 device 수와 ADB 상태 요약만 shell로 전달한다. -- **macos-platform**: 앱 sandbox 안에서 ADB binary 실행 가능 여부는 platform domain과 함께 검토한다. +- **artifact-flow**: 설치할 staged APK path와 metadata만 입력으로 받고 Jenkins 인증/다운로드 상태에는 의존하지 않는다. settings 화면에 ADB diagnostics panel이 있어도 진단 타입과 loader semantics는 device-console 소유다. +- **app-shell**: pending install과 선택 device handoff는 shell이 조율하고, device-console은 설치/logcat 요청을 수행한다. +- **macos-platform**: bundled ADB 리소스, sandbox, codesign, packaging 제약은 macos-platform에서 관리하고, runtime 선택과 command semantics는 device-console에서 관리한다. ## 금지 사항 - device serial, logcat 원문에 secret이 포함될 수 있으므로 불필요하게 tracked 파일에 저장하지 않는다. - split APK/APKS/AAB 설치를 단일 APK 설치 흐름에 섞어 임시 처리하지 않는다. - 무한 logcat stream을 dispose 없이 방치하지 않는다. +- 화면 widget에서 ADB binary 경로, environment, server port를 직접 구성하지 않는다. diff --git a/agent-ops/rules/project/domain/macos-platform/rules.md b/agent-ops/rules/project/domain/macos-platform/rules.md index 4b8b310..fe853fd 100644 --- a/agent-ops/rules/project/domain/macos-platform/rules.md +++ b/agent-ops/rules/project/domain/macos-platform/rules.md @@ -1,34 +1,44 @@ --- domain: macos-platform -last_rule_review_commit: no-commit -last_rule_updated_at: 2026-06-08 +last_rule_review_commit: c1c4c41886f44727ad5b9297ec164198d1dd5bd9 +last_rule_updated_at: 2026-06-14 --- # macos-platform ## 목적 / 책임 -macOS desktop target의 bundle metadata, entitlement, URL scheme, runner 설정을 담당한다. +macOS desktop target의 bundle metadata, entitlement, URL scheme, runner 설정, bundled ADB resource packaging, certified build/signing/notarization tooling을 담당한다. ## 포함 경로 - `macos/Runner/Info.plist` — bundle metadata와 `appsok://` URL scheme - `macos/Runner/Configs/` — product name, bundle identifier, build config +- `macos/Runner/AppDelegate.swift`, `macos/Runner/MainFlutterWindow.swift`, `macos/Runner/Base.lproj/` — macOS app/window/menu runner wiring - `macos/Runner/*.entitlements` — sandbox/network 권한 +- `macos/Runner/Resources/adb-runtime/` — bundled ADB runtime metadata와 NOTICE - `macos/Runner.xcodeproj/`, `macos/Runner.xcworkspace/` — Xcode project/workspace 설정 - `macos/Flutter/GeneratedPluginRegistrant.swift` — Flutter plugin 등록 +- `scripts/build-certified-macos.sh` — Flutter gate, Developer ID signing, notarization, final zip 생성 +- `scripts/setup-appsok-ci-secrets.sh` — SOPS age key, encrypted CI secret, notary profile setup +- `.sops.yaml`, `secrets/*.sops.json` — encrypted CI signing/notary input 설정과 암호화 payload ## 제외 경로 - `lib/src/services/jenkins_client.dart` — network 호출 자체는 `artifact-flow` 책임 - `lib/src/services/adb_service.dart` — ADB command wrapper는 `device-console` 책임 - `lib/src/theme/` — 시각 스타일은 `app-shell` 책임 +- `agent-test/` — 검증 명령 라우팅은 테스트 룰 책임 ## 주요 구성 요소 - `AppInfo.xcconfig` — macOS 앱 표시 이름과 bundle id - `Info.plist` — URL scheme 등록 - `DebugProfile.entitlements`, `Release.entitlements` — sandbox와 network client 권한 +- `Runner.xcodeproj` build phase — pinned Android platform-tools `adb`를 app bundle resource로 복사하고 adhoc sign +- `GeneratedPluginRegistrant.swift` — `app_links`, `flutter_secure_storage_darwin`, `webview_flutter_wkwebview` plugin 등록 +- `build-certified-macos.sh` — release build, bundled `adb` signing, app signing, notarization/staple/assessment packaging +- `setup-appsok-ci-secrets.sh` — SOPS-encrypted CI input 생성과 `notarytool` profile 저장 ## 유지할 패턴 @@ -36,14 +46,19 @@ macOS desktop target의 bundle metadata, entitlement, URL scheme, runner 설정 - bundle identifier는 `com.tokilabs.appsok` 기준으로 관리한다. - URL scheme은 식별자 규칙상 `appsok://`을 유지한다. - Jenkins 호출에는 network client entitlement가 필요하다. +- Release entitlement는 필요 권한만 유지하고, Debug/Profile 권한과 차이가 있으면 목적을 명확히 둔다. +- bundled ADB는 `source.properties`의 pinned `Pkg.Revision`과 실제 `adb version`을 맞춘 뒤 app resource로 복사한다. +- app bundle 안의 `adb-runtime/adb`는 app signing/notarization 전에 별도로 codesign 검증한다. +- CI signing/notary secret은 SOPS-encrypted payload와 macOS Keychain profile로만 다루고 raw password/key를 tracked 문서나 로그에 남기지 않는다. - 배포 전에는 sandbox 상태에서 ADB binary 실행과 USB 접근 가능 여부를 macOS host에서 검증한다. - macOS build/signing 검증은 local container가 아니라 standard remote Mac runner `toki@toki-labs.com`의 `$HOME/docker/services/code-server/data/volume/workspace/appsok` checkout을 기준으로 한다. -- 원격에는 valid codesigning identity가 확인되어 있지만, notary credential profile은 별도 확인 전까지 미확정으로 둔다. +- certified build script는 `flutter analyze`, `flutter test`, `flutter build macos` gate 이후 signing/notarization/package 순서를 유지한다. +- 원격에는 valid codesigning identity가 확인되어 있지만, notary credential profile은 profile availability 확인 전까지 미확정으로 둔다. ## 다른 도메인과의 경계 - **artifact-flow**: deep link payload가 Jenkins job/build/artifact를 가리킬 수 있으나 parsing/권한 확인은 artifact-flow에서 담당한다. -- **device-console**: ADB 실행 권한과 packaging 제약은 macos-platform에서 관리하고, command semantics는 device-console에서 관리한다. +- **device-console**: bundled ADB resource, sandbox, codesign, packaging 제약은 macos-platform에서 관리하고, runtime 선택과 command semantics는 device-console에서 관리한다. - **app-shell**: 앱 이름과 window metadata는 platform 설정에서 관리하고, 화면 layout은 app-shell에서 관리한다. ## 금지 사항 @@ -51,3 +66,4 @@ macOS desktop target의 bundle metadata, entitlement, URL scheme, runner 설정 - entitlement를 넓힐 때 사유 없이 sandbox를 해제하지 않는다. - macOS 설정 파일을 Flutter 자동 생성물과 충돌하는 방식으로 수동 대량 편집하지 않는다. - notarization, signing, MDM 배포 전제를 확인하지 않고 배포 가능하다고 단정하지 않는다. +- SOPS key, keychain password, Apple ID password, notary credential 원문을 tracked 파일, task log, 최종 응답에 기록하지 않는다. diff --git a/agent-ops/rules/project/rules.md b/agent-ops/rules/project/rules.md index 8dc37ae..153c0b2 100644 --- a/agent-ops/rules/project/rules.md +++ b/agent-ops/rules/project/rules.md @@ -55,10 +55,11 @@ | 경로 패턴 | 도메인 | rules.md | |----------|--------|----------| -| `lib/main.dart`, `lib/src/app.dart`, `lib/src/features/app_shell.dart`, `lib/src/theme/**` | app-shell | `agent-ops/rules/project/domain/app-shell/rules.md` | -| `lib/src/features/builds/**`, `lib/src/features/settings/**`, `lib/src/models/jenkins_build.dart`, `lib/src/services/jenkins_client.dart`, `lib/src/services/token_store.dart` | artifact-flow | `agent-ops/rules/project/domain/artifact-flow/rules.md` | +| `lib/main.dart`, `lib/src/app.dart`, `lib/src/features/app_shell.dart`, `lib/src/models/pending_install.dart`, `lib/src/theme/**` | app-shell | `agent-ops/rules/project/domain/app-shell/rules.md` | +| `lib/src/features/builds/**`, `lib/src/features/settings/**`, `lib/src/models/jenkins_build.dart`, `lib/src/services/jenkins_client.dart`, `lib/src/services/jenkins_artifact_session.dart`, `lib/src/services/artifact_staging_service.dart`, `lib/src/services/token_store.dart` | artifact-flow | `agent-ops/rules/project/domain/artifact-flow/rules.md` | | `lib/src/features/devices/**`, `lib/src/features/console/**`, `lib/src/models/adb_device.dart`, `lib/src/services/adb_service.dart` | device-console | `agent-ops/rules/project/domain/device-console/rules.md` | | `macos/**` | macos-platform | `agent-ops/rules/project/domain/macos-platform/rules.md` | +| `scripts/build-certified-macos.sh`, `scripts/setup-appsok-ci-secrets.sh`, `.sops.yaml`, `secrets/*.sops.json` | macos-platform | `agent-ops/rules/project/domain/macos-platform/rules.md` | ## 스킬 라우팅 diff --git a/agent-roadmap/phase/workflow-integration/milestones/macos-build-ci.md b/agent-roadmap/archive/phase/workflow-integration/milestones/macos-build-ci.md similarity index 94% rename from agent-roadmap/phase/workflow-integration/milestones/macos-build-ci.md rename to agent-roadmap/archive/phase/workflow-integration/milestones/macos-build-ci.md index 4bfb717..73be329 100644 --- a/agent-roadmap/phase/workflow-integration/milestones/macos-build-ci.md +++ b/agent-roadmap/archive/phase/workflow-integration/milestones/macos-build-ci.md @@ -11,7 +11,7 @@ Teams deep link와 설치 이력 작업으로 들어가기 전에, 원격 Mac ru ## 상태 -[검토중] +[완료] ## 승격 조건 @@ -63,15 +63,15 @@ Teams deep link와 설치 이력 작업으로 들어가기 전에, 원격 Mac ru ## 완료 리뷰 -- 상태: 요청됨 +- 상태: 승인됨 - 요청일: 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 이동을 승인했다 + - [x] 사용자가 완료 결과를 확인했다 + - [x] archive 이동을 승인했다 - 리뷰 코멘트: 전체화면 전용 검증은 제품 목표가 아니므로 완료 조건에서 제외한다. 일반 창 기반 업무 흐름 확인은 각 후속 기능 Milestone의 smoke에서 필요할 때 다룬다. ## 범위 제외 @@ -111,6 +111,7 @@ Teams deep link와 설치 이력 작업으로 들어가기 전에, 원격 Mac ru - 반복 실행 명령: `scripts/build-certified-macos.sh`. - 2026-06-14 docs/test: `docs/macos-certified-build.md`와 `test/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 이동 승인. diff --git a/agent-roadmap/phase/workflow-integration/PHASE.md b/agent-roadmap/phase/workflow-integration/PHASE.md index af3c8d0..8f35a72 100644 --- a/agent-roadmap/phase/workflow-integration/PHASE.md +++ b/agent-roadmap/phase/workflow-integration/PHASE.md @@ -14,10 +14,10 @@ MVP 설치 흐름을 Teams/Jenkins 알림과 연결하고, 반복 설치와 실 완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다. 스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다. -- [검토중] macOS 빌드 CI와 인증 빌드 - - 경로: `agent-roadmap/phase/workflow-integration/milestones/macos-build-ci.md` +- [완료] macOS 빌드 CI와 인증 빌드 + - 경로: `agent-roadmap/archive/phase/workflow-integration/milestones/macos-build-ci.md` - 요약: Teams deep link와 설치 이력 작업 전에 원격 Mac build/CI baseline과 Developer ID notarized 인증 빌드 절차를 확정한다. -- [계획] Teams deep link 설치 진입 +- [진행중] Teams deep link 설치 진입 - 경로: `agent-roadmap/phase/workflow-integration/milestones/teams-deep-link.md` - 요약: Teams/Jenkins 메시지의 `appsok://` 링크로 특정 job/build/artifact 설치 화면에 바로 진입한다. - [계획] 설치 세션 이력과 오류 리포트 diff --git a/agent-roadmap/phase/workflow-integration/milestones/teams-deep-link.md b/agent-roadmap/phase/workflow-integration/milestones/teams-deep-link.md index 2ad72a5..1fb77ff 100644 --- a/agent-roadmap/phase/workflow-integration/milestones/teams-deep-link.md +++ b/agent-roadmap/phase/workflow-integration/milestones/teams-deep-link.md @@ -11,7 +11,7 @@ Teams/Jenkins 알림에 포함된 `appsok://` 링크를 클릭하면 AppSok이 ## 상태 -[계획] +[진행중] ## 승격 조건 @@ -77,4 +77,5 @@ Teams/Jenkins가 만들고 AppSok이 해석할 URL 형식을 정한다. - 작업 현황: - 2026-06-14: `ADB 콘솔과 logcat` 완료 후 다음 활성 Milestone으로 지정했다. - 2026-06-14: macOS build/CI와 인증 빌드 gate를 먼저 확인하기 위해 `macOS 빌드 CI와 인증 빌드` 뒤로 순서를 조정했다. + - 2026-06-14: `macOS 빌드 CI와 인증 빌드` 완료 승인 및 archive 이동 후 다음 활성 Milestone으로 지정했다. - 확인 필요: Teams payload 형식, Jenkins 알림 템플릿 변경 가능 여부 diff --git a/scripts/setup-appsok-ci-secrets.sh b/scripts/setup-appsok-ci-secrets.sh index 282542a..6120b4d 100755 --- a/scripts/setup-appsok-ci-secrets.sh +++ b/scripts/setup-appsok-ci-secrets.sh @@ -35,18 +35,6 @@ prompt_plain() { printf -v "$var" '%s' "$value" } -prompt_secret() { - local label="$1" - local var="$2" - local value - printf "%s: " "$label" > /dev/tty - stty -echo < /dev/tty - IFS= read -r value < /dev/tty - stty echo < /dev/tty - printf "\n" > /dev/tty - printf -v "$var" '%s' "$value" -} - mkdir -p "$(dirname "$AGE_KEY")" "$(dirname "$SECRET_FILE")" if [ ! -f "$AGE_KEY" ]; then @@ -60,9 +48,17 @@ if [ -z "$AGE_RECIPIENT" ]; then exit 1 fi +SOPS_PATH_REGEX="$(SECRET_FILE="$SECRET_FILE" python3 - <<'PY' +import os +import re + +print(re.escape(os.environ["SECRET_FILE"]) + "$") +PY +)" + cat > .sops.yaml <