Repository navigation
[sk-33] Feature: Kotlin Workflow CLI 구현 #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Jeong-Rae
wants to merge
102
commits into
develop
Choose a base branch
from
feature/sk-33
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
102 commits
Select commit
Hold shift + click to select a range
9666f63
Feature: Workflow CLI 기반과 Review 게시 구현
Jeong-Rae f5f0ef0
Feature: Review Thread와 Stack 동기화 구현
Jeong-Rae c04f690
Docs: Workflow CLI 구현 아키텍처 확정
Jeong-Rae 44ffe02
Build: Kotlin Workflow CLI 프로젝트 구성
Jeong-Rae 18ea245
Feature: Workflow Domain 규칙 구현
Jeong-Rae 45368da
Feature: Native 친화 JSON 처리 구현
Jeong-Rae b2bb71c
Chore: Workflow CLI 빌드 스크립트 포맷 적용
Jeong-Rae 93faaf9
Feature: Workflow JSON 결과 계약 구현
Jeong-Rae 14966c6
Feature: Workflow 상태 Aggregate 구현
Jeong-Rae 608d969
Feature: Workflow 외부 포트 계약 구현
Jeong-Rae dbadcf2
Feature: Workflow 실패 코드 계약 확장
Jeong-Rae 5081bea
Docs: Workflow 라이브러리 선택 기준 추가
Jeong-Rae a8a6397
Refactor: Workflow 직렬화를 라이브러리로 전환
Jeong-Rae a8c61ed
Docs: Workflow Git CLI 연동 원칙 명시
Jeong-Rae 19c7609
Test: Workflow 테스트를 Kotest로 전환
Jeong-Rae e514adf
Feature: Okio Workflow 저장소 어댑터 구현
Jeong-Rae 2e2cc92
Feature: Workflow Application 유스 케이스 구현
Jeong-Rae 9b4f827
Feature: Clikt Workflow 명령 어댑터 구현
Jeong-Rae a518606
Feature: 로컬 Git CLI 어댑터 구현
Jeong-Rae ed9327d
Docs: Workflow Domain과 Adapter KDoc 한글화
Jeong-Rae 003b735
Docs: Workflow Application KDoc 한글화
Jeong-Rae 2d6d050
Docs: Workflow Review KDoc 한글화
Jeong-Rae d5ba2ad
Docs: Workflow 빌드 주석 정리
Jeong-Rae 6eef2e0
Feature: 로컬 검증 어댑터 추가
Jeong-Rae f956949
Feature: 배포와 공개 Gate 유스케이스 추가
Jeong-Rae 1808554
Fix: Sync 충돌 복구 상태를 영속화
Jeong-Rae aca7d9e
Feature: 리뷰 Gate 유스케이스 추가
Jeong-Rae b71b96e
Feature: Review 게시 생명주기 구현
Jeong-Rae 4e9db79
Feature: Workflow ID를 Store에서 발급
Jeong-Rae 3a6fd34
Feature: 배포 후보 생명주기 구현
Jeong-Rae 08ea4c7
Feature: 외부 공개 생명주기 구현
Jeong-Rae f2a22d6
Feature: Merge Queue 통합 생명주기 구현
Jeong-Rae 617e76f
Feature: GitHub CLI 어댑터 연결
Jeong-Rae d6bf4a4
Feature: 로컬 Workflow 어댑터 구현
Jeong-Rae 0c76a71
Docs: AI Review 미지원 범위 명시
Jeong-Rae 2b298ba
Build: Native CLI 실행 계약 검증
Jeong-Rae 0937d8e
Feature: Store 기반 SubTask ID 발급
Jeong-Rae de6a09b
Feature: Stack 동기화와 Git 정리 계약 확장
Jeong-Rae 572e81e
Feature: Merge 이후 안전 정리 구현
Jeong-Rae 9099ab9
Feature: 외부 Workflow 이벤트 처리
Jeong-Rae 1bea927
Feature: GitHub Issue Task 어댑터 추가
Jeong-Rae 39ed845
Test: Sync 충돌 JSON 계약 검증
Jeong-Rae 95b7b78
Feature: Workflow CLI 런타임 연결
Jeong-Rae 02143cd
Test: Workflow CLI 명령 계약 보강
Jeong-Rae c710d10
Feature: 외부 배포 CLI 어댑터 추가
Jeong-Rae a426190
Feature: 외부 공개 CLI 어댑터 추가
Jeong-Rae 8b918eb
Feature: Feature Flag CLI 어댑터 추가
Jeong-Rae 4c33a44
Feature: 배포 상태 이벤트 재개
Jeong-Rae 1f5511c
Fix: Git 정리와 Worktree 경계 강화
Jeong-Rae 4d6f8fb
Feature: 외부 배포 런타임 연결
Jeong-Rae 853de9b
Docs: 외부 Provider와 Native 실행 계약 추가
Jeong-Rae 77a4031
Fix: Git ref 입력 검증 강화
Jeong-Rae 2a102e2
Fix: Merge 이후 정리 재시도 보강
Jeong-Rae 769c945
Fix: 배포와 Cleanup 실패 정보 보존
Jeong-Rae f5551c4
Docs: 외부 이벤트 ingress 경계 명시
Jeong-Rae fe26cfc
Fix: CLI 인자 오류 JSON 계약 보강
Jeong-Rae f3550dd
Fix: Review 변경 상태 영속화
Jeong-Rae a6f6120
Feature: Feature Flag별 Release 생성
Jeong-Rae 7a15dc0
Feature: 누적 배포 후보 선택
Jeong-Rae 27403b3
Fix: Delivery Gate 검증 강화
Jeong-Rae afa3103
Fix: GitHub Review thread 식별자 보존
Jeong-Rae e2e86b5
Fix: Release 생성 revision 재동기화
Jeong-Rae ffde81b
Fix: Review 상태 차단 계약 통합
Jeong-Rae 3c4aa21
Feature: 배포와 공개 이벤트 진행 연결
Jeong-Rae 355e185
Fix: CI 조회 revision 계약 수정
Jeong-Rae be7315f
Test: 런타임 GitHub 계약 보강
Jeong-Rae 87cd87f
Refactor: 본문 파일 읽기를 Okio Adapter로 분리
Jeong-Rae af0995f
Fix: Review provider revision 분리
Jeong-Rae 378cc81
Test: 조건과 결과 중심 이름 정리
Jeong-Rae 509dba4
Build: Workflow Native 바이너리 설치
Jeong-Rae 8a7a20d
Docs: Provider revision 계약 명시
Jeong-Rae 6560fa0
Docs: Workflow 런타임 구성 명시
Jeong-Rae 3fda3b6
Docs: 외부 Task 동기화 범위 정리
Jeong-Rae 7085319
Fix: 일반 Review thread lifecycle 연결
Jeong-Rae 981cb60
Fix: Merge Queue revision 동기화
Jeong-Rae f0d83e2
Fix: 병합 후 정리 재시도 영속화
Jeong-Rae 52ed9fc
Fix: 런타임 구성 오류 JSON 계약 통합
Jeong-Rae defba12
Fix: PR 본문 템플릿 검증
Jeong-Rae 16849d4
Fix: 일반 Review 작성자와 답글 재시도 판별
Jeong-Rae f530b3b
Fix: Review 답글 요청 식별자 안정화
Jeong-Rae 396540e
Fix: 병합 후 정리 Git SHA 재시도 검증
Jeong-Rae 0cb2c33
Fix: GitHub 답글 재시도와 상태 검사 복구
Jeong-Rae 5222b7d
Fix: provider SHA와 코드 fingerprint 경계 강화
Jeong-Rae b296517
Test: 런타임 fixture를 Review 계약에 정렬
Jeong-Rae 074d03d
Build: Workflow Native 바이너리 갱신
Jeong-Rae ca8adff
Fix: 필수 검증과 원격 게시 가능성 확인
Jeong-Rae 40a647b
Fix: 실제 GitHub Merge Queue 규칙 확인
Jeong-Rae df4f253
Fix: 코드 줄 코멘트에 GitHub SHA 사용
Jeong-Rae cbefb5e
Docs: check의 상태 기록과 게시 검사 범위 명시
Jeong-Rae a0856a6
Build: 최신 Workflow Native 바이너리 반영
Jeong-Rae 0bfe20a
Refactor: GitHub 검사 상태 변환 통합
Jeong-Rae c3b3888
Refactor: 트랜잭션 조회 결과 분기 명확화
Jeong-Rae c3c6432
Refactor: Worktree 문맥을 한 번에 조회
Jeong-Rae 36b4263
Refactor: Git 게시 가능성 검사를 종료 상태로 단순화
Jeong-Rae 9bccff8
Build: 단순화한 Workflow Native 바이너리 갱신
Jeong-Rae a5581f4
Refactor: 런타임 이벤트 조립 책임 분리
Jeong-Rae 9c6b1b5
Build: 이벤트 분리 후 Native 바이너리 갱신
Jeong-Rae 27ead3a
Docs: PR 본문 템플릿 등록
Jeong-Rae 9439755
Fix: Kotlin Workflow CLI PR 리뷰 의견 반영
Jeong-Rae b249809
Build: Workflow Native 실행 파일 재생성
Jeong-Rae c3fb857
Fix: Agent 댓글 작성자 분류 우선순위 수정
Jeong-Rae 4c7da7a
Refactor: Workflow CLI 기능 경계와 계정 검증 정리
Jeong-Rae File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| ## 해결하려는 문제 | ||
|
|
||
| > 어떤 문제를 해결하는지 적습니다. 필요에 따라 사진이나 링크를 첨부하고, 어떤 문제를 마주했는지에 집중해서 설명합니다. | ||
|
|
||
| ## 필요성 | ||
|
|
||
| > 문제를 해결해야 하는 이유를 적습니다. 어떤 불편이 생기는지, 왜 문제로 다뤄야 하는지 설명합니다. | ||
|
|
||
| ## 해결 방법 | ||
|
|
||
| > 문제를 어떤 방식으로 해결하는지 작성합니다. 설계부터 코드, 테스트까지 엔지니어링 영역에서 고려한 내용을 편안하게 설명합니다. | ||
|
|
||
| ## 한계와 트레이드오프 | ||
|
|
||
| > 해결하지 못해 추가 작업이 필요하거나 함께 고려했지만 선택하지 않은 내용을 공유합니다. 리뷰 과정에서 선택지와 그에 따른 영향을 폭넓게 검토할 수 있도록 적습니다. | ||
|
|
||
| ## 기존 기능에 미치는 영향 | ||
|
|
||
| > 기존 기능과 달라지는 부분이나 영향을 줄 수 있는 변경을 적습니다. | ||
|
|
||
| ## 예외 및 실패 사례 | ||
|
|
||
| > 아직 해결하지 못한 예외나 실패 사례가 있다면 작성합니다. 해결하지 못한 사항도 드러내어 이후 개선할 목표로 이어질 수 있게 합니다. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # Workflow 명령줄 도구 | ||
|
|
||
| Workflow CLI(Command line interface, 명령줄 인터페이스)는 저장소 루트에서 실행합니다. | ||
|
|
||
| ```sh | ||
| tools/workflow/bin/workflow <명령> [인자와 옵션] | ||
| ``` | ||
|
|
||
| ## 명령 | ||
|
|
||
| | 명령 | 필수 입력 | 주요 옵션과 동작 | | ||
| | --- | --- | --- | | ||
| | `start` | `--task <task-id>`, `--request-id <request-id>`, `--title <text>` | `--requires <subtask-id>`로 직접 선행 작업을 지정합니다. | | ||
| | `check` | 없음 | 현재 Worktree 변경을 검증합니다. | | ||
| | `review open` | `--body-file <경로>`, `--risk` (`normal` 또는 `high`) | 변경을 게시하고 초안 PR(Pull request)을 엽니다. | | ||
| | `review show` | 없음 | `--diff`, `--threads` (`open` 또는 `all`)를 지원합니다. 기본 조회 범위는 `open`입니다. | | ||
| | `review update` | `--revision <revision>` | 변경 커밋을 다시 게시합니다. `--body-file <경로>`를 지정하면 PR 설명도 갱신합니다. | | ||
| | `review comment` | `--revision <revision>`, `--level` (`R`, `C` 또는 `A`), `--body <내용>` 또는 `--body-file <경로>` | 본문 입력은 하나만 지정합니다. 인라인 댓글에는 `--path <파일>`과 `--line <번호>`를 함께 지정합니다. | | ||
| | `review reply` | `--revision <revision>`, `--thread <thread-id>`, `--body <내용>` 또는 `--body-file <경로>` | 본문 입력은 하나만 지정합니다. | | ||
| | `review resolve` | `--revision <revision>`, `--thread <thread-id>` | 지정한 리뷰 대화를 해결 상태로 바꿉니다. | | ||
| | `stack` | `--requires <subtask-id>` 또는 `--clear` | 두 옵션 중 하나만 지정합니다. | | ||
| | `sync` | 없음 | `--continue`로 동기화를 계속하거나 `--abort`로 중단합니다. 두 옵션은 함께 쓸 수 없습니다. | | ||
| | `status` | 없음 | 대상 조회에는 `--subtask`, `--task`, `--candidate`, `--release` 중 하나를 지정합니다. | | ||
| | `gate ready <subtask-id>` | `--review-revision <revision>` | PR을 사람 검토 대상으로 전환합니다. | | ||
| | `gate approve <subtask-id>` | `--change-revision <revision>` | 코드 변경을 승인합니다. | | ||
| | `gate deploy <candidate-id>` | `candidate-id` 인자 | Production Canary 배포를 승인합니다. | | ||
| | `gate release <release-id>` | `release-id` 인자 | 외부 공개를 승인합니다. | | ||
|
|
||
| 각 작업 명령에 `--json`을 붙이면 결과를 구조화된 JSON으로 출력합니다. | ||
|
|
||
| `--allow-account-mismatch`는 `review update`, `review comment`, `review reply`, `review resolve`, `gate ready`, `gate approve`, `stack`, `sync`에서 사용할 수 있습니다. PR 변경 전에 현재 `gh` 사용자와 PR 작성자를 비교하며, 다르면 기본적으로 중단합니다. 이 옵션으로 계정 차이만 허용하면 작업을 계속하고 경고를 표준 오류(stderr)에 출력합니다. `--json` 결과는 표준 출력(stdout)에 유지됩니다. | ||
|
|
||
| ```sh | ||
| tools/workflow/bin/workflow start --task SK-33 --request-id sk-33-start --title '문서 추가' | ||
| tools/workflow/bin/workflow review open --body-file /tmp/pr-body.md --risk normal | ||
| tools/workflow/bin/workflow review show --diff --threads all --json | ||
| tools/workflow/bin/workflow review comment --revision abc123 --level C --body '[Agent] 검토 의견입니다.' | ||
| tools/workflow/bin/workflow review update --revision rv-4 --allow-account-mismatch --json | ||
| tools/workflow/bin/workflow status --subtask sk-33 | ||
| ``` | ||
|
|
||
| ## 댓글과 인증 | ||
|
|
||
| 에이전트가 `review comment` 또는 `review reply`로 작성하는 댓글 본문은 `[Agent]`로 시작해야 합니다. `--body`와 `--body-file` 모두 같은 규칙을 적용합니다. | ||
|
|
||
| Workflow CLI는 설정된 인증을 사용하며 로그인이나 인증 절차를 다시 실행하지 않습니다. |
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| import io.springkit.workflow.build.WorkflowNativeSmokeTest | ||
|
|
||
| plugins { | ||
| kotlin("jvm") version "2.4.20" | ||
| kotlin("plugin.serialization") version "2.4.20" | ||
| application | ||
| id("com.diffplug.spotless") version "8.10.2" | ||
| id("org.graalvm.buildtools.native") version "1.1.14" | ||
| } | ||
|
|
||
| group = "io.springkit" | ||
|
|
||
| version = "0.1.0-SNAPSHOT" | ||
|
|
||
| java { | ||
| toolchain { | ||
| languageVersion = JavaLanguageVersion.of(21) | ||
| } | ||
| } | ||
|
|
||
| repositories { | ||
| mavenCentral() | ||
| } | ||
|
|
||
| application { | ||
| mainClass.set("io.springkit.workflow.MainKt") | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation("com.github.ajalt.clikt:clikt:5.0.1") | ||
| implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.11.0") | ||
| implementation("com.squareup.okio:okio:3.18.1") | ||
|
|
||
| testImplementation("io.kotest:kotest-assertions-core:6.2.4") | ||
| testImplementation("io.kotest:kotest-runner-junit5:6.2.4") | ||
| testImplementation("com.squareup.okio:okio-fakefilesystem:3.18.1") | ||
| testRuntimeOnly("org.junit.platform:junit-platform-launcher") | ||
| } | ||
|
|
||
| kotlin { | ||
| jvmToolchain(21) | ||
| } | ||
|
|
||
| spotless { | ||
| isEnforceCheck = false | ||
|
|
||
| kotlin { | ||
| target("src/*/kotlin/**/*.kt", "buildSrc/src/**/*.kt") | ||
| ktfmt("0.63").metaStyle() | ||
| } | ||
|
|
||
| kotlinGradle { | ||
| target("*.gradle.kts", "buildSrc/*.gradle.kts") | ||
| ktfmt("0.63").metaStyle() | ||
| } | ||
| } | ||
|
|
||
| tasks.withType<Test>().configureEach { | ||
| useJUnitPlatform() | ||
| } | ||
|
|
||
| graalvmNative { | ||
| binaries { | ||
| named("main") { | ||
| imageName = "workflow" | ||
| buildArgs.add("--initialize-at-build-time=kotlin.DeprecationLevel") | ||
| } | ||
| } | ||
| } | ||
|
|
||
| val installWorkflowNative = | ||
| tasks.register<Copy>("installWorkflowNative") { | ||
| dependsOn("nativeCompile") | ||
| from(layout.buildDirectory.dir("native/nativeCompile")) { | ||
| include("workflow") | ||
| } | ||
| into(layout.projectDirectory.dir("bin")) | ||
| } | ||
|
|
||
| tasks.register<WorkflowNativeSmokeTest>("workflowNativeSmokeTest") { | ||
| dependsOn(installWorkflowNative) | ||
| repositoryRoot.set(layout.projectDirectory.dir("../..")) | ||
| executable.set(layout.projectDirectory.file("bin/workflow")) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| plugins { | ||
| `kotlin-dsl` | ||
| } | ||
|
|
||
| repositories { | ||
| mavenCentral() | ||
| } |
189 changes: 189 additions & 0 deletions
189
.../workflow/buildSrc/src/main/kotlin/io/springkit/workflow/build/WorkflowNativeSmokeTest.kt
|
Jeong-Rae marked this conversation as resolved.
Resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| package io.springkit.workflow.build | ||
|
|
||
| import groovy.json.JsonSlurper | ||
| import java.io.ByteArrayOutputStream | ||
| import java.io.File | ||
| import java.nio.charset.StandardCharsets | ||
| import javax.inject.Inject | ||
| import org.gradle.api.DefaultTask | ||
| import org.gradle.api.file.DirectoryProperty | ||
| import org.gradle.api.file.RegularFileProperty | ||
| import org.gradle.api.tasks.InputFile | ||
| import org.gradle.api.tasks.Internal | ||
| import org.gradle.api.tasks.PathSensitive | ||
| import org.gradle.api.tasks.PathSensitivity | ||
| import org.gradle.api.tasks.TaskAction | ||
| import org.gradle.process.ExecOperations | ||
|
|
||
| /* | ||
| * Native 바이너리의 시작과 JSON 결과 계약을 확인하는 최소 실행 검증입니다. | ||
| */ | ||
| abstract class WorkflowNativeSmokeTest : DefaultTask() { | ||
| @get:Inject abstract val execOperations: ExecOperations | ||
|
|
||
| /* | ||
| * 실행 위치와 환경 변수에만 사용하므로 입력 fingerprint에서 제외한 저장소 루트입니다. | ||
| */ | ||
| @get:Internal abstract val repositoryRoot: DirectoryProperty | ||
|
|
||
| /* | ||
| * 시작과 JSON 결과 계약을 검증할 Native 실행 파일입니다. | ||
| */ | ||
| @get:InputFile | ||
| @get:PathSensitive(PathSensitivity.RELATIVE) | ||
| abstract val executable: RegularFileProperty | ||
|
|
||
| @TaskAction | ||
| fun verifyNativeBinary() { | ||
| val repositoryRootFile = repositoryRoot.get().asFile | ||
| val executableFile = executable.get().asFile | ||
| val stateFile = temporaryDir.resolve("state.json") | ||
| stateFile.writeText( | ||
| """ | ||
| { | ||
| "schema_version": 1, | ||
| "store_revision": 0, | ||
| "tasks": { | ||
| "smoke-task": { | ||
| "id": "smoke-task", | ||
| "external_id": {"value": "SMOKE-1"}, | ||
| "title": "Native smoke task", | ||
| "state": "OPEN", | ||
| "sub_task_ids": [] | ||
| } | ||
| } | ||
| } | ||
| """ | ||
| .trimIndent() | ||
| ) | ||
|
|
||
| val help = invoke(executableFile, repositoryRootFile, stateFile, "--help") | ||
| check(help.exitCode == 0) { | ||
| "Native 바이너리의 --help 실행이 실패했습니다. 종료 코드: ${help.exitCode}\n${help.stderr}" | ||
| } | ||
| check(help.stdout.contains("Usage: workflow")) { | ||
| "Native 바이너리가 도움말을 출력하지 않았습니다.\n${help.stdout}" | ||
| } | ||
|
|
||
| val success = | ||
| invoke( | ||
| executableFile, | ||
| repositoryRootFile, | ||
| stateFile, | ||
| "status", | ||
| "--task", | ||
| "smoke-task", | ||
| "--json", | ||
| ) | ||
| requireJsonResult(success, expectedType = "success", expectedExitCode = 0) | ||
|
|
||
| val failure = | ||
| invoke( | ||
| executableFile, | ||
| repositoryRootFile, | ||
| stateFile, | ||
| "status", | ||
| "--subtask", | ||
| "missing-subtask", | ||
| "--json", | ||
| ) | ||
| val failureJson = requireJsonResult(failure, expectedType = "failure", expectedExitCode = 1) | ||
| val failureData = failureJson["data"] as? Map<*, *> | ||
| check(failureData?.get("code") == "SUBTASK_NOT_FOUND") { | ||
| "대표 JSON 실패 코드가 예상과 다릅니다.\n${failure.stdout}" | ||
| } | ||
|
|
||
| val configurationFailure = | ||
| invoke( | ||
| executableFile, | ||
| repositoryRootFile, | ||
| stateFile, | ||
| "status", | ||
| "--json", | ||
| extraEnvironment = | ||
| mapOf( | ||
| "WORKFLOW_DEPLOYMENT_COMMAND" to "[\"deploy\"]", | ||
| "WORKFLOW_RELEASE_COMMAND" to "", | ||
| ), | ||
| ) | ||
| val configurationJson = | ||
| requireJsonResult(configurationFailure, expectedType = "failure", expectedExitCode = 1) | ||
| val configurationData = configurationJson["data"] as? Map<*, *> | ||
| check(configurationData?.get("code") == "INVALID_ARGUMENT") { | ||
| "구성 오류가 공통 JSON 실패로 변환되지 않았습니다.\n${configurationFailure.stdout}" | ||
| } | ||
|
|
||
| val actorConfigurationFailure = | ||
| invoke( | ||
| executableFile, | ||
| repositoryRootFile, | ||
| stateFile, | ||
| "status", | ||
| "--json", | ||
| extraEnvironment = mapOf("WORKFLOW_ACTOR_KIND" to "HUMAN"), | ||
| ) | ||
| val actorConfigurationJson = | ||
| requireJsonResult(actorConfigurationFailure, expectedType = "failure", expectedExitCode = 1) | ||
| val actorConfigurationData = actorConfigurationJson["data"] as? Map<*, *> | ||
| check(actorConfigurationData?.get("code") == "INVALID_ARGUMENT") { | ||
| "주체 종류 구성 오류가 공통 JSON 실패로 변환되지 않았습니다.\n${actorConfigurationFailure.stdout}" | ||
| } | ||
| } | ||
|
|
||
| private fun invoke( | ||
| executable: File, | ||
| repositoryRoot: File, | ||
| stateFile: File, | ||
| vararg arguments: String, | ||
| extraEnvironment: Map<String, String> = emptyMap(), | ||
| ): NativeInvocation { | ||
| val stdout = ByteArrayOutputStream() | ||
| val stderr = ByteArrayOutputStream() | ||
| val result = execOperations.exec { | ||
| commandLine(executable.absolutePath, *arguments) | ||
| workingDir(repositoryRoot) | ||
| environment("WORKFLOW_REPO_ROOT", repositoryRoot.absolutePath) | ||
| environment("WORKFLOW_STATE_FILE", stateFile.absolutePath) | ||
| extraEnvironment.forEach { (name, value) -> environment(name, value) } | ||
| standardOutput = stdout | ||
| errorOutput = stderr | ||
| isIgnoreExitValue = true | ||
| } | ||
| return NativeInvocation( | ||
| exitCode = result.exitValue, | ||
| stdout = stdout.toString(StandardCharsets.UTF_8.name()), | ||
| stderr = stderr.toString(StandardCharsets.UTF_8.name()), | ||
| ) | ||
| } | ||
|
|
||
| private fun requireJsonResult( | ||
| invocation: NativeInvocation, | ||
| expectedType: String, | ||
| expectedExitCode: Int, | ||
| ): Map<*, *> { | ||
| check(invocation.exitCode == expectedExitCode) { | ||
| "JSON 경로의 종료 코드가 다릅니다. " + | ||
| "기대값: $expectedExitCode, 실제값: ${invocation.exitCode}\n${invocation.stderr}" | ||
| } | ||
| val lines = invocation.stdout.lineSequence().filter(String::isNotBlank).toList() | ||
| check(lines.size == 1) { | ||
| "JSON 경로는 표준 출력에 JSON 객체 하나만 기록해야 합니다.\n${invocation.stdout}" | ||
| } | ||
| val json = lines.single().trim() | ||
| val parsed = JsonSlurper().parseText(json) as? Map<*, *> | ||
| check(parsed != null) { "JSON 경로가 객체를 출력하지 않았습니다.\n$json" } | ||
| check(parsed["type"] == expectedType) { | ||
| "JSON 결과 type이 다릅니다. 기대값: $expectedType\n$json" | ||
| } | ||
| check(parsed["data"] is Map<*, *>) { | ||
| "JSON 결과에 data가 없습니다.\n$json" | ||
| } | ||
| return parsed | ||
| } | ||
|
|
||
| private data class NativeInvocation( | ||
| val exitCode: Int, | ||
| val stdout: String, | ||
| val stderr: String, | ||
| ) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| org.gradle.configuration-cache=true | ||
| org.gradle.parallel=true | ||
| kotlin.code.style=official |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| rootProject.name = "workflow" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.