From 93aeeffbec81d170ec7a424d8491ea7d21e79041 Mon Sep 17 00:00:00 2001 From: leedongmyung Date: Wed, 20 Aug 2025 15:47:52 +0900 Subject: [PATCH 01/11] =?UTF-8?q?jenkins=20parameter=20modify=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/config.xml | 778 ++++++++++++++++++++++++++ assets/pipeline-test2.yaml | 127 ++--- lib/oto/commands/command.dart | 5 +- lib/oto/commands/jenkins/jenkins.dart | 53 ++ lib/oto/data/command_data.dart | 18 +- lib/oto/data/command_data.g.dart | 32 ++ pubspec.yaml | 2 +- 7 files changed, 920 insertions(+), 95 deletions(-) create mode 100644 assets/config.xml create mode 100644 lib/oto/commands/jenkins/jenkins.dart diff --git a/assets/config.xml b/assets/config.xml new file mode 100644 index 0000000..981e3de --- /dev/null +++ b/assets/config.xml @@ -0,0 +1,778 @@ + + + + 빌드 가이드 문서 + +https://lgtest.atlassian.net/wiki/spaces/FE/pages/78217452/AOS+Jenkins + false + + + + 15 + -1 + -1 + -1 + false + + + + + + url + LT환경 설정화면이 없이 고정주소 빌드가 필요할때 사용해 주세요. +공백일경우 앱시작시 LT환경 설정이 나옵니다. +(http또는 https를 포함한 주소를 넣어주세요. 공백이 포함되거나, 마지막 /가 포함되면 정상 실행이 되지 않을수 있습니다.) + false + + + modify_app_id + App ID를 변경합니다. 'com.lguplus.mobile.cs' 에서 추가로 값이 추가되어 운영버전의 앱과 중복 설치 가능하게 됩니다. +예를들어 myapp로 설정시 App ID 'com.lguplus.mobile.cs.myapp'으로 빌드되며, 앱이름은 '당신의 U+ (myapp)로 설정됩니다. 앱아이콘은 dev띠를 두릅니다. +공백일경우 운영과 동일한 App ID로 빌드됩니다. +(텍스트내 공백무시, 대문자 무시, 기호불가, 10자 한정, 10자 초과시 자름) + dev + true + + + slack_message + 빌드 완료시 Slack에 메세지를 보낼때, 어떤용도의 빌드인지 알기 위한 판별용 메세지입니다. +등록된 사용자의 경우 멘션(@김아무개) 사용도 가능합니다. + false + + + branch + 빌드할 브런치입니다. 특정 feature 브런치용 빌드를 원하신다면 설정에서 이 항목에 추가해주세요. +(수정권한이 없으면 앱파트에 요청해주세요.) + + + main + develop + release/7.0.6 + release/7.0.7 + release/7.0.10 + release/7.0.11 + release/6.0.38_test + feature/DCBGIT-21704_U+2.0크롬판별_이슈 + feature/DCBGIT-20848_LT빌드-자동화 + feature/DCBGIT-18853_딥링크_이동페이지_변경 + feature/DCBGWBS-6721_가속화002_챗봇 + feature/DCBGQA-6078_용어사전pdf_다운로드이슈 + feature/DCBGIT-24352_디바이스식별자전달 + + + + + slack_channel + 알림을 보낼 Slack 채널을 선택합니다. + + + 디지털fe-앱빌드 + 디지털fe-앱빌드_테스트 + + + + + debuggable + 디버깅 가능한 빌드인지 여부입니다. 체크시 디버깅 가능한 빌드로 빌드 됩니다. + true + + + share + 외부공유용 (Firebase 이용) + false + + + obfuscation + 난독화를 할지 여부 입니다. + false + + + release + 메인 url을 제외한 빌드세팅을 Release환경으로 선택하여 빌드 합니다. (메인 url은 위에 있는 url필드 값을 따라갑니다.) + false + + + BuildData + 빌드용 스크립트입니다. 터치하지 마세요. + --- +############################ Properties ############################ + +property: + workspace: '${WORKSPACE}' + slackChannel: '${slack_channel}' + slackMessage: '${slack_message}' + branch: '${branch}' + url: '${url}' + appID: '${modify_app_id}' + share: '${share}' + obfuscation: '${obfuscation}' + release: '${release}' + urlValue: https://mstg.lguplus.com + fileUrl: http://febuild.uhdcsre.com:8080/job/mcs-aos/${BUILD_NUMBER}/artifact/app/build/outputs/apk/mobileCS/lt/{FILE} + urlMessage: '' + appIDMessage: '' + portValue: '' + enableDevTool: 'true' + gradlePath: <!property.workspace>/app/build.gradle + stringsPath: <!property.workspace>/app/src/main/res/values/strings.xml + manifestPath: <!property.workspace>/app/src/main/AndroidManifest.xml + buildPath: <!property.workspace>/app/build/outputs/apk/mobileCS/lt + config: | + { + "version": "VERSION", + "versionCode": VERSION_CODE, + "gitHash": "GIT_HASH", + "buildDate": "BUILD_DATE" + } + templateLt: | + lt { + debuggable ${debuggable} + signingConfig null + + buildConfigField 'boolean', 'ENABLE_DEVTOOL', "{ENABLE_DEVTOOL}" + buildConfigField 'boolean', 'DEV', "${debuggable}" + buildConfigField 'String', 'DEBUG_LOG_TAG', '"MobileCS_STG"' + buildConfigField 'String', 'HTTP_WEB_URL', '"{HTTP_URL}"' + buildConfigField 'String', 'WEB_URL', '"{URL}"' + buildConfigField 'String', 'PUSH_APPLICATION_ID', '"custm_FCM1"' + buildConfigField 'String', 'PUSH_SERVICE_ID', '"30153"' + buildConfigField 'String', 'PUSH_URL', '"http://222.231.13.33:5556"' + buildConfigField 'String', 'PUSH_AUTH', '"auth=0000002359;C20384A50EBCD4FD2A1B"' + buildConfigField 'String', 'CHATBOT_URL', '"https://chatbot-stg.lguplus.com/?fromChan=APP"' + buildConfigField 'String', 'FIDO_URL', '"https://stg-onps.uplus.co.kr"' + buildConfigField 'String', 'FIDO_BIZ_API_URL', '"https://stg.uplus.co.kr/uhdc/fo/apcm/authbio/v1"' + buildConfigField 'String', 'FIDO_SITE_ID', '"SIT01UPLUS0000000000"' + buildConfigField 'String', 'FIDO_SVC_ID', '"SVC01SIT01UPLUS00000"' + buildConfigField 'String', 'USIM_AGENT_API_KEY', '"a6AwmI2XEWup9MALI/Z/ASzDs87gcNmKifk2iyUUChs="' + buildConfigField 'String', 'SERVER_TYPE', '"STG"' + buildConfigField "java.util.Map<String, String>", "LT_ENVIRONMENT_MAP", "new java.util.HashMap<String, String>() {{ " + + " put(\"QA (https)\", \"https://mstg.lguplus.com\");" + + " put(\"QA\", \"http://mstg.lguplus.com\");" + + " put(\"운영\", \"https://app.lguplus.com\");" + + " put(\"PRE\", \"https://mpre.lguplus.com\");" + + " put(\"DEV\", \"http://mdev.uplus.com\");" + + "}}" + + manifestPlaceholders = [buildType: ""] + } + templateRelease: | + lt { + debuggable ${debuggable} + minifyEnabled false + shrinkResources false + signingConfig null + + buildConfigField 'boolean', 'ENABLE_DEVTOOL', "{ENABLE_DEVTOOL}" + buildConfigField 'boolean', 'DEV', "${debuggable}" + buildConfigField 'String', 'DEBUG_LOG_TAG', '"MobileCS"' + buildConfigField 'String', 'HTTP_WEB_URL', '"{HTTP_URL}"' + buildConfigField 'String', 'WEB_URL', '"{URL}"' + buildConfigField 'String', 'PUSH_APPLICATION_ID', '"custm_FCM1"' + buildConfigField 'String', 'PUSH_SERVICE_ID', '"21016"' + buildConfigField 'String', 'PUSH_URL', '"http://upushgw.uplus.co.kr:5556"' + buildConfigField 'String', 'PUSH_AUTH', '"auth=0000002415;CDAC132152FCB4F4499F"' + buildConfigField 'String', 'CHATBOT_URL', '"https://chatbot.lguplus.com/?fromChan=APP"' + buildConfigField 'String', 'FIDO_URL', '"https://onps.uplus.co.kr"' + buildConfigField 'String', 'FIDO_BIZ_API_URL', '"https://app.lguplus.com/uhdc/fo/apcm/authbio/v1"' + buildConfigField 'String', 'FIDO_SITE_ID', '"SIT01UPLUS0000000000"' + buildConfigField 'String', 'FIDO_SVC_ID', '"SVC01SIT01UPLUS00000"' + buildConfigField 'String', 'USIM_AGENT_API_KEY', '"mV/yWnRgD2wQn5sjzokKGVJZDdVKDnLPkvS4cG+jwZE="' + buildConfigField 'String', 'SERVER_TYPE', '"PROD"' + buildConfigField "java.util.Map<String, String>", "LT_ENVIRONMENT_MAP", "new java.util.HashMap<String, String>()" + + manifestPlaceholders = [buildType: ""] + } + slackMessageAdd: | + "text": "<!property.slackMessage>", + slackMessageJson: | + { + "channel": "<!property.slackChannel>", + {SLACK_MESSAGE} + "attachments": [ + { + "color": "#81CA3F", + "author_name": "Android", + "fields": [ + { + "value": "```Builder: ${BUILD_USER}\nJob URL: ${BUILD_URL}\nBranch: ${GIT_BRANCH}\nGitHash: ${GIT_COMMIT}\nVersion: {VERSION}\nVersion Code: {VERSION_CODE}\nRelease 환경: ${release}\n{URL}DevTool 활성: {DEVTOOL}\n{APPID}Date: {DATE}```" + } + ], + "image_url": "https://api.qrserver.com/v1/create-qr-code/?data={FILE_URL}&size=150x150", + "actions": [ + { + "type": "button", + "name": "build", + "text": "Download", + "url": "{FILE_URL}" + } + ] + } + ] + } + + + +############################# Pipeline ############################# + +pipeline: + id: main + workflow: + # Set app info + - exe: create-app + + # Set envValue + - if: + condition-bool: <!property.release> == true + on-true: + - exe: set-release + on-false: + - exe: set-lt + + # Set urlValue + - contain: + list: <!property.url> + target: '{url}' + on-false: + - exe: parse-url + - if: + condition-string: <!property.port> != 443 + on-true: + - if: + condition-string: <!property.port> != 80 + on-true: + - exe: set-port + - exe: set-url + + # Gradle에 Signing 정보 입력 + - exe: gradle-read + - exe: append-sign + - exe: replace-http-url + - exe: replace-url + - exe: replace-env + - exe: gradle-write + + - contain: + list: <!property.appID> + target: '{modify_app_id}' + on-false: + - exe: set-appid-message + # 앱이름 변경 + - exe: strings-read + - exe: app-rename + - exe: strings-write + + # 파일 권한 및 아이콘 변경 + - exe: manifest-read + - exe: replace-icon + - exe: replace-permission + - exe: manifest-write + + # Listing Files + - exe: files + - foreach: + iterator: <!property.files> + setValue: <@property.file> + on-do: + # Pacckage name replace + - exe: file-read + - exe: replace-package + - exe: file-write + + # Config 작성 + - exe: set-config + - exe: write-config + + # Gradle 빌드 + - exe: build + + # Slack Message가 빈값일때 empty 세팅 + - contain: + list: <!property.slackMessage> + target: '{slack_message}' + on-true: + - exe: set-slack-message-empty + + # Listing Build Files + - exe: files-build + - foreach: + iterator: <!property.files> + setValue: <@property.fileBuild> + on-do: + - contain: + list: <!property.fileBuild> + target: output-metadata.json + on-true: + - exe: read-build-meta + - if: + condition-string: <!property.enableDevTool> == false + on-true: + - exe: replace-file-name + - exe: rename-build-file + - exe: set-file-name + + + - exe: set-slack-message + - exe: slack + +############################# Commands ############################# + +commands: +### Create App Data +- command: CreateAppData + id: create-app + param: + scm: Git + name: mcs + relativeAssetPath: app/src/main/assets + setVersion: <@property.version> + setHash: <@property.hash> + setDate: <@property.date> + +### Set Lt +- command: SetValue + id: set-lt + param: + values-string: + envValue: <!property.templateLt> + +### Set Release +- command: SetValue + id: set-release + param: + values-string: + envValue: <!property.templateRelease> + urlValue: http://app.lguplus.com + +### Parse URL +- command: URLInfo + id: parse-url + param: + url: <!property.url> + setScheme: <@property.scheme> + setHost: <@property.host> + setPort: <@property.port> + +### Set Port Value +- command: SetValue + id: set-port + param: + values-string: + portValue: :<!property.port> + +### Set default url +- command: SetValue + id: set-url + param: + values-string: + urlValue: <!property.scheme>://<!property.host><!property.portValue> + urlMessage: 'URL: <!property.scheme>://<!property.host><!property.portValue>\n' + enableDevTool: 'false' + +### Gradle Read +- command: FileRead + id: gradle-read + param: + showPrint: false + path: <!property.gradlePath> + setContent: <@property.gradle> + +### Set Signing Option +- command: StringReplace + id: append-sign + param: + showPrint: false + text: <!property.gradle> + pair: + - from: android { + to: | + android { + signingConfigs { + Lt { + storeFile file("keystore.dat") + storePassword "123456" + keyAlias "kingkor" + keyPassword "123456" + } + } + setValue: <@property.gradle> + +### Replace http url +- command: StringReplace + id: replace-http-url + param: + showPrint: true + text: <!property.urlValue> + pair: + - from: https:// + to: http:// + setValue: <@property.httpUrlValue> + +### Replace url +- command: StringReplace + id: replace-url + param: + showPrint: true + text: <!property.envValue> + pair: + - from: '{HTTP_URL}' + to: <!property.httpUrlValue> + - from: '{URL}' + to: <!property.urlValue> + - from: '{ENABLE_DEVTOOL}' + to: <!property.enableDevTool> + setValue: <@property.envValue> + +### Replace env +- command: StringReplacePattern + id: replace-env + param: + startAt: 0 + showPrint: true + startPattern: 'lt {' + endPattern: ' }' + text: <!property.gradle> + value: <!property.envValue> + setValue: <@property.gradle> + +### Gradle Write +- command: FileWrite + id: gradle-write + param: + path: <!property.gradlePath> + content: <!property.gradle> + +### App ID Message +- command: SetValue + id: set-appid-message + param: + values-string: + appIDMessage: '변경된 App ID: com.lguplus.mobile.cs.<!property.appID>\n' + +### Strings Read +- command: FileRead + id: strings-read + param: + showPrint: false + path: <!property.stringsPath> + setContent: <@property.strings> + +### Replace App Name +- command: StringReplace + id: app-rename + param: + showPrint: false + text: <!property.strings> + pair: + - from: <string name="app_name">당신의 U+</string> + to: <string name="app_name">당유(<!property.appID>)</string> + setValue: <@property.strings> + +### Strings Write +- command: FileWrite + id: strings-write + param: + path: <!property.stringsPath> + content: <!property.strings> + +### Manifest Read +- command: FileRead + id: manifest-read + param: + showPrint: false + path: <!property.manifestPath> + setContent: <@property.manifest> + +### Replace Icon +- command: StringReplace + id: replace-icon + param: + showPrint: false + text: <!property.manifest> + pair: + - from: android:icon="@drawable/ic_launcher" + to: android:icon="@drawable/ic_launcher_dev" + setValue: <@property.manifest> + +### Replace Permission +- command: StringReplace + id: replace-permission + param: + showPrint: false + text: <!property.manifest> + pair: + - from: </application> + to: | + </application> + + <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/> + + setValue: <@property.manifest> + +### Manifest Write +- command: FileWrite + id: manifest-write + param: + path: <!property.manifestPath> + content: <!property.manifest> + +### Files Listing +- command: Files + id: files + param: + path: <!property.workspace>/app + recursive: true + ignoreRegExs: + - ^.*\/\.[a-zA-Z0-9_-]+\/.* # .git .idea etc.. + - ^.*\.(png|jpg|jpeg|gif|bmp)$ # image files + - ^.*\.(txt|so|mk|crt|ttf)$ # ignore ext + - /build/ + - /buildScript/ + - /schemas/ + - /libs/ + - /aars/ + - /mobileCS/ + - /.DS_Store + - /proguard-rules.pro + - /lint.xml + - /.gitignore + setFiles: <@property.files> + +### File Read +- command: FileRead + id: file-read + param: + showPrint: false + path: <!property.file> + setContent: <@property.fileContent> + +### Replace Package +- command: StringReplace + id: replace-package + param: + showPrint: false + text: <!property.fileContent> + pair: + - from: com.lguplus.mobile.cs + to: com.lguplus.mobile.cs.<!property.appID> + setValue: <@property.fileContent> + +### Strings Write +- command: FileWrite + id: file-write + param: + path: <!property.file> + content: <!property.fileContent> + +### Print +- command: Print + id: print + param: + message: 'File: <!property.file>' + +### Set Config +- command: StringReplace + id: set-config + param: + showPrint: false + text: <!property.config> + pair: + - from: GIT_HASH + to: ${GIT_COMMIT} + - from: BUILD_DATE + to: <!property.date> + setValue: <@property.config> + +### Write Config +- command: FileWrite + id: write-config + param: + path: <!property.workspace>/app/src/main/assets/config.json + content: <!property.config> + +### Build Gradle +- command: Shell + id: build + param: + commands: + - ./gradlew clean assembleLt + +### Build Files Listing +- command: Files + id: files-build + param: + path: <!property.workspace>/app/build/outputs/apk/mobileCS/lt + recursive: false + setFiles: <@property.files> + +### Read build meta +- command: JsonReaderFile + id: read-build-meta + param: + path: <!property.fileBuild> + pair: + - from: elements[0].versionCode + setValue: <@property.versionCode> + - from: elements[0].versionName + setValue: <@property.versionName> + - from: elements[0].outputFile + setValue: <@property.fileBuildName> + - from: elements[0].outputFile + setValue: <@property.fileBuildReplacedName> + +### Replace file name +- command: StringReplace + id: replace-file-name + param: + showPrint: false + text: <!property.fileBuildName> + pair: + - from: '_lt_' + to: '_<!property.host>_' + setValue: <@property.fileBuildReplacedName> + +### Rename Build File +- command: Rename + id: rename-build-file + param: + renameMap: + <!property.workspace>/app/build/outputs/apk/mobileCS/lt/<!property.fileBuildName>: <!property.workspace>/app/build/outputs/apk/mobileCS/lt/<!property.fileBuildReplacedName> + +### Set File Name +- command: StringReplace + id: set-file-name + param: + showPrint: false + text: <!property.fileUrl> + pair: + - from: '{FILE}' + to: <!property.fileBuildReplacedName> + setValue: <@property.fileUrl> + +### Set Slack Message +- command: StringReplace + id: set-slack-message + param: + showPrint: false + text: <!property.slackMessageJson> + pair: + - from: '{SLACK_MESSAGE}' + to: <!property.slackMessageAdd> + - from: '{APPID}' + to: <!property.appIDMessage> + - from: '{DATE}' + to: <!property.date> + - from: '{VERSION}' + to: <!property.versionName> + - from: '{VERSION_CODE}' + to: <!property.versionCode> + - from: '{URL}' + to: <!property.urlMessage> + - from: '{DEVTOOL}' + to: <!property.enableDevTool> + - from: '{FILE_URL}' + to: <!property.fileUrl> + setValue: <@property.slackMessageJson> + +### Set Slack Message to empty +- command: SetValue + id: set-slack-message-empty + param: + values-string: + slackMessageAdd: '' + +### Slack +- command: Slack + id: slack + param: + token: xoxb-3457711939825-8629587578534-ysH4Q5R0lM8gdgJ8dx3z6xI7 + messageJson: <!property.slackMessageJson> + idMap: + 박형윤: U03L21XV6LE + 이동명: U05A94D57RS + 심재진: U03L8HZCN75 + 이미영: U04H7HMV4R2 + 김시형: U03LYCJ1XU0 + 김가영: U050BN7EH8W + 김낙운: U05DRP0N295 + 한희경: U03KU1YJUG7 + false + + + + + + 2 + + + https://gitlab.uhdcsre.com/app-developer/lgup-mcs-aos.git + bfd6fb6a-e36e-4d12-87a8-4c6ca93bc28b + + + + + */${branch} + + + false + + + + mac-mini-m2 + false + false + false + false + + false + + + # Load .zprofile if it exists +if [ -f ~/.zprofile ]; then + source ~/.zprofile +fi + +# Load .bash_profile if it exists +if [ -f ~/.bash_profile ]; then + source ~/.bash_profile +fi + +# Load .bashrc if it exists (optional) +if [ -f ~/.bashrc ]; then + source ~/.bashrc +fi + +# Load .zshrc if it exists (optional) +if [ -f ~/.zshrc ]; then + source ~/.zshrc +fi + +echo $PATH +BASEDIR=$(dirname $0) +#echo "===> Script location: ${BASEDIR}" +#cd ${BASEDIR}/../../.. +echo "===> Build Project Path: ${PWD}" + +echo ${BUILD_USER} +echo ${BUILD_USER_ID} + +oto exe -j + + + + + + app/build/outputs/apk/mobileCS/lt/*.apk + false + false + false + true + true + false + + + + + xterm + + + \ No newline at end of file diff --git a/assets/pipeline-test2.yaml b/assets/pipeline-test2.yaml index 31736b2..1e7e827 100644 --- a/assets/pipeline-test2.yaml +++ b/assets/pipeline-test2.yaml @@ -1,108 +1,51 @@ --- property: - workspace: C:/Users/r0bin/AppData/Roaming/DarkSoulsIII - saveFolder: /01100001112a7a14 - savePath: /DS30000.sl2 + workspace: . + value: + - test1 + - test2 + - test3 + - test4 + pipeline: id: main workflow: - - contain: - list: this is test - target: back - on-true: - - exe: print0 - - exe: read-web - - exe: json-read-web - - exe: json-read-local - - exe: diff - - if: - condition-bool: == true - on-true: - - exe: info - - if: - condition-date: < - on-true: - - exe: json-write-local - - exe: upload - - if: - condition-date: > - on-true: - - exe: json-write-web - - exe: download + - exe: read + - exe: param-modify + # - exe: write - commands: -- command: Print - id: print0 +### Strings Read +- command: FileRead + id: read param: - message: test + showPrint: false + path: /assets/config.xml + setContent: <@property.content> -- command: FileInfo - id: info +### Replace +- command: StringReplace + id: replace param: - path: - setInfo: <@property.info> - -- command: WebRequest - id: read-web - param: - url: https://toki-labs.com/cdn/save/darksoulIII/save.json - setResponse: <@property.web> - -- command: JsonReader - id: json-read-web - param: - json: + showPrint: true + text: pair: - - from: lastSaved - setValue: <@property.lastSavedWeb> + - from: + to: + setValue: <@property.content> -- command: JsonReaderFile - id: json-read-local +- command: JenkinsParameterModify + id: param-modify param: - path: /save.json - pair: - - from: lastSaved - setValue: <@property.lastSavedLocal> + content: + name: branch + value: + setContent: <@property.content> -- command: Print - id: print +### Gradle Write +- command: FileWrite + id: write param: - message: change save file - -- command: FileDiffCheck - id: diff - param: - paths: - - - setDiff: <@property.diff> - -- command: JsonWriterFile - id: json-write-local - param: - path: /save.json - pair: - - from: lastSaved - value: - -- command: Copy - id: upload - param: - copyMap: - : \\192.168.0.97\Macintosh HD\Users\toki\docker\nginx\home\cdn\save\darksoulIII - /save.json : \\192.168.0.97\Macintosh HD\Users\toki\docker\nginx\home\cdn\save\darksoulIII - -- command: JsonWriterFile - id: json-write-web - param: - path: /save.json - pair: - - from: lastSaved - value: - -- command: Copy - id: download - param: - copyMap: - \\192.168.0.97\Macintosh HD\Users\toki\docker\nginx\home\cdn\save\darksoulIII\DS30000.sl2 : \ No newline at end of file + path: /Users/leedongmyung/works/oto_cli/assets/config_new.xml + content: \ No newline at end of file diff --git a/lib/oto/commands/command.dart b/lib/oto/commands/command.dart index be1b430..8d1359d 100644 --- a/lib/oto/commands/command.dart +++ b/lib/oto/commands/command.dart @@ -24,6 +24,7 @@ import 'package:oto_cli/oto/commands/aws/awscli.dart'; import 'package:oto_cli/oto/commands/docker/docker.dart'; import 'package:oto_cli/oto/commands/git/git_hub.dart'; import 'package:oto_cli/oto/commands/gradle/gradle.dart'; +import 'package:oto_cli/oto/commands/jenkins/jenkins.dart'; import 'package:oto_cli/oto/commands/jira/jira.dart'; import 'package:oto_cli/oto/commands/process/process.dart'; import 'package:oto_cli/oto/commands/proto/protobuf.dart'; @@ -117,7 +118,8 @@ enum CommandType { ProcessRun, ProcessKill, SMBAuth, - Delay + Delay, + JenkinsParameterModify } abstract class Command { @@ -193,6 +195,7 @@ abstract class Command { CommandType.ProcessKill: () => ProcessKill(), CommandType.SMBAuth: () => SMBAuth(), CommandType.Delay: () => Delay(), + CommandType.JenkinsParameterModify: () => JenkinsParameterModify(), }; factory Command.byType(CommandType type) { diff --git a/lib/oto/commands/jenkins/jenkins.dart b/lib/oto/commands/jenkins/jenkins.dart new file mode 100644 index 0000000..0d89614 --- /dev/null +++ b/lib/oto/commands/jenkins/jenkins.dart @@ -0,0 +1,53 @@ +import 'package:oto_cli/oto/commands/command.dart'; +import 'package:oto_cli/oto/data/command_data.dart'; +import 'package:xml/xml.dart' as xml; + +class JenkinsParameterModify extends Command { + Function? get error => null; + + @override + Future execute(DataCommand command) async { + var data = DataJenkinsParameterModify.fromJson(getParam(command)); + + final document = xml.XmlDocument.parse(data.content!); + var project = document.findAllElements('project').first; + for( var child in project.children ) { + if(child is xml.XmlElement && child.localName == 'properties') { + var property = child.findAllElements('hudson.model.ParametersDefinitionProperty').first; + var definitions = property.findAllElements('parameterDefinitions').first.childElements; + for(var def in definitions) { + var paramName = def.getElement('name'); + if(paramName?.innerText == data.name) { + switch(def.localName) { + case 'hudson.model.BooleanParameterDefinition': + if(data.defaultValue != null) { + var defaultValue = def.getElement('defaultValue'); + defaultValue?.innerText = data.defaultValue; + } + break; + case 'hudson.model.ChoiceParameterDefinition': + if(data.value is List) { + var choices = def.getElement('choices'); + choices?.children.clear(); + var a = xml.XmlElement(xml.XmlName('a'), [xml.XmlAttribute(xml.XmlName('class'), 'string-array')]); + for(var item in data.value) { + a.children.add(xml.XmlElement(xml.XmlName('string'), [], [xml.XmlText(item)])); + } + choices?.children.add(a); + } + break; + case 'hudson.model.TextParameterDefinition': + break; + case 'hudson.model.StringParameterDefinition': + break; + } + } + } + break; + } + } + print(document.toXmlString()); + + return await complete(0, command); + } +} \ No newline at end of file diff --git a/lib/oto/data/command_data.dart b/lib/oto/data/command_data.dart index 2f12588..04c3ac8 100644 --- a/lib/oto/data/command_data.dart +++ b/lib/oto/data/command_data.dart @@ -1204,7 +1204,7 @@ class DataSMBAuthorize extends DataParam { Map toJson() => _$DataSMBAuthorizeToJson(this); } -//Smb Authorize +//Delay @JsonSerializable() class DataDelay extends DataParam { DataDelay(); @@ -1219,3 +1219,19 @@ class DataDelay extends DataParam { @override Map toJson() => _$DataDelayToJson(this); } + +@JsonSerializable() +class DataJenkinsParameterModify extends DataParam { + DataJenkinsParameterModify(); + + late String? content; + late String? name; + late dynamic value; + late dynamic defaultValue; + late String? setContent; + + factory DataJenkinsParameterModify.fromJson(Map json) => + _$DataJenkinsParameterModifyFromJson(json); + @override + Map toJson() => _$DataJenkinsParameterModifyToJson(this); +} diff --git a/lib/oto/data/command_data.g.dart b/lib/oto/data/command_data.g.dart index ed4c701..670d2f6 100644 --- a/lib/oto/data/command_data.g.dart +++ b/lib/oto/data/command_data.g.dart @@ -124,6 +124,7 @@ const _$CommandTypeEnumMap = { CommandType.ProcessKill: 'ProcessKill', CommandType.SMBAuth: 'SMBAuth', CommandType.Delay: 'Delay', + CommandType.JenkinsParameterModify: 'JenkinsParameterModify', }; DataParam _$DataParamFromJson(Map json) => DataParam() @@ -2087,3 +2088,34 @@ Map _$DataDelayToJson(DataDelay instance) => { 'minute': instance.minute, 'hour': instance.hour, }; + +DataJenkinsParameterModify _$DataJenkinsParameterModifyFromJson( + Map json) => + DataJenkinsParameterModify() + ..workspace = json['workspace'] as String? + ..passExitCodes = (json['passExitCodes'] as List?) + ?.map((e) => (e as num).toInt()) + .toList() + ..setResult = json['setResult'] as String? + ..setExitCode = json['setExitCode'] as String? + ..showPrint = json['showPrint'] as bool? + ..content = json['content'] as String? + ..name = json['name'] as String? + ..value = json['value'] + ..defaultValue = json['defaultValue'] + ..setContent = json['setContent'] as String?; + +Map _$DataJenkinsParameterModifyToJson( + DataJenkinsParameterModify instance) => + { + 'workspace': instance.workspace, + 'passExitCodes': instance.passExitCodes, + 'setResult': instance.setResult, + 'setExitCode': instance.setExitCode, + 'showPrint': instance.showPrint, + 'content': instance.content, + 'name': instance.name, + 'value': instance.value, + 'defaultValue': instance.defaultValue, + 'setContent': instance.setContent, + }; diff --git a/pubspec.yaml b/pubspec.yaml index e3132a9..082232b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: color: ^3.0.0 file_hasher: ^0.1.0+0 cron: ^0.6.1 - xml: ^6.3.0 + xml: ^6.6.1 dev_dependencies: lints: ^5.0.0 From 21a12ced3b466573b48245cbaecd1ef5d2b33a2a Mon Sep 17 00:00:00 2001 From: leedongmyung Date: Wed, 20 Aug 2025 15:53:50 +0900 Subject: [PATCH 02/11] =?UTF-8?q?jenkins=20param=20modify=20file=20?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/pipeline-test2.yaml | 4 ++-- lib/oto/commands/jenkins/jenkins.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/pipeline-test2.yaml b/assets/pipeline-test2.yaml index 1e7e827..cffcabc 100644 --- a/assets/pipeline-test2.yaml +++ b/assets/pipeline-test2.yaml @@ -13,7 +13,7 @@ pipeline: workflow: - exe: read - exe: param-modify - # - exe: write + - exe: write commands: ### Strings Read @@ -47,5 +47,5 @@ commands: - command: FileWrite id: write param: - path: /Users/leedongmyung/works/oto_cli/assets/config_new.xml + path: /Users/leedongmyung/works/oto_cli/assets/config.xml content: \ No newline at end of file diff --git a/lib/oto/commands/jenkins/jenkins.dart b/lib/oto/commands/jenkins/jenkins.dart index 0d89614..2d869bf 100644 --- a/lib/oto/commands/jenkins/jenkins.dart +++ b/lib/oto/commands/jenkins/jenkins.dart @@ -46,7 +46,7 @@ class JenkinsParameterModify extends Command { break; } } - print(document.toXmlString()); + setProperty(data.setContent!, document.toXmlString(), showPrint: data.showPrint); return await complete(0, command); } From 369b4fb743a0116338f02fc9ef25d0486a8db59e Mon Sep 17 00:00:00 2001 From: leedongmyung Date: Thu, 21 Aug 2025 15:20:11 +0900 Subject: [PATCH 03/11] jenkins parameter update --- assets/pipeline-test2.yaml | 2 +- lib/oto/commands/jenkins/jenkins.dart | 82 +++++++++++++++------------ lib/oto/data/command_data.dart | 2 - lib/oto/data/command_data.g.dart | 2 - 4 files changed, 48 insertions(+), 40 deletions(-) diff --git a/assets/pipeline-test2.yaml b/assets/pipeline-test2.yaml index cffcabc..ee15870 100644 --- a/assets/pipeline-test2.yaml +++ b/assets/pipeline-test2.yaml @@ -47,5 +47,5 @@ commands: - command: FileWrite id: write param: - path: /Users/leedongmyung/works/oto_cli/assets/config.xml + path: /assets/config.xml content: \ No newline at end of file diff --git a/lib/oto/commands/jenkins/jenkins.dart b/lib/oto/commands/jenkins/jenkins.dart index 2d869bf..1f46144 100644 --- a/lib/oto/commands/jenkins/jenkins.dart +++ b/lib/oto/commands/jenkins/jenkins.dart @@ -9,45 +9,57 @@ class JenkinsParameterModify extends Command { Future execute(DataCommand command) async { var data = DataJenkinsParameterModify.fromJson(getParam(command)); - final document = xml.XmlDocument.parse(data.content!); - var project = document.findAllElements('project').first; - for( var child in project.children ) { - if(child is xml.XmlElement && child.localName == 'properties') { - var property = child.findAllElements('hudson.model.ParametersDefinitionProperty').first; - var definitions = property.findAllElements('parameterDefinitions').first.childElements; - for(var def in definitions) { - var paramName = def.getElement('name'); - if(paramName?.innerText == data.name) { - switch(def.localName) { - case 'hudson.model.BooleanParameterDefinition': - if(data.defaultValue != null) { - var defaultValue = def.getElement('defaultValue'); - defaultValue?.innerText = data.defaultValue; - } - break; - case 'hudson.model.ChoiceParameterDefinition': - if(data.value is List) { - var choices = def.getElement('choices'); - choices?.children.clear(); - var a = xml.XmlElement(xml.XmlName('a'), [xml.XmlAttribute(xml.XmlName('class'), 'string-array')]); - for(var item in data.value) { - a.children.add(xml.XmlElement(xml.XmlName('string'), [], [xml.XmlText(item)])); - } - choices?.children.add(a); - } - break; - case 'hudson.model.TextParameterDefinition': - break; - case 'hudson.model.StringParameterDefinition': - break; + var startId = ''; + var start = data.content?.indexOf(startId); + var end = + data.content?.indexOf(''); + var startParam = start! + startId.length; + var endParam = end!; + var paramContent = data.content?.substring(start + startId.length, end); + startId = '${data.name}'; + start = paramContent + ?.substring(0, paramContent.indexOf(startId)) + .lastIndexOf('<'); + var findContent = paramContent?.substring(start!); + end = findContent?.indexOf('>'); + var element = findContent?.substring(1, end! + 1); + startId = ' toJson() => _$DataSlackFileToJson(this); } - //Slack Build @JsonSerializable() class DataSlackBuild extends DataSlackSender { @@ -1227,7 +1226,6 @@ class DataJenkinsParameterModify extends DataParam { late String? content; late String? name; late dynamic value; - late dynamic defaultValue; late String? setContent; factory DataJenkinsParameterModify.fromJson(Map json) => diff --git a/lib/oto/data/command_data.g.dart b/lib/oto/data/command_data.g.dart index 670d2f6..61465ed 100644 --- a/lib/oto/data/command_data.g.dart +++ b/lib/oto/data/command_data.g.dart @@ -2102,7 +2102,6 @@ DataJenkinsParameterModify _$DataJenkinsParameterModifyFromJson( ..content = json['content'] as String? ..name = json['name'] as String? ..value = json['value'] - ..defaultValue = json['defaultValue'] ..setContent = json['setContent'] as String?; Map _$DataJenkinsParameterModifyToJson( @@ -2116,6 +2115,5 @@ Map _$DataJenkinsParameterModifyToJson( 'content': instance.content, 'name': instance.name, 'value': instance.value, - 'defaultValue': instance.defaultValue, 'setContent': instance.setContent, }; From c59903750c0463e6de5e72d1fa0e23b79ef32d9c Mon Sep 17 00:00:00 2001 From: leedongmyung Date: Thu, 21 Aug 2025 20:08:35 +0900 Subject: [PATCH 04/11] git branch list up --- assets/pipeline-test2.yaml | 10 ++++++++ lib/oto/commands/command.dart | 2 ++ lib/oto/commands/git/git.dart | 40 ++++++++++++++++++++++++++++++++ lib/oto/data/command_data.dart | 29 +++++++++++++++++++++++ lib/oto/data/command_data.g.dart | 38 ++++++++++++++++++++++++++++++ 5 files changed, 119 insertions(+) diff --git a/assets/pipeline-test2.yaml b/assets/pipeline-test2.yaml index ee15870..0afa70f 100644 --- a/assets/pipeline-test2.yaml +++ b/assets/pipeline-test2.yaml @@ -12,6 +12,7 @@ pipeline: id: main workflow: - exe: read + - exe: branch - exe: param-modify - exe: write @@ -35,6 +36,15 @@ commands: to: setValue: <@property.content> +### List up branches +- command: GitBranch + id: branch + param: + path: /Users/toki/works/lgup-mcs-aos + startDay: 20 + setBranches: <@property.value> + +### Modify param - command: JenkinsParameterModify id: param-modify param: diff --git a/lib/oto/commands/command.dart b/lib/oto/commands/command.dart index 8d1359d..0d113b4 100644 --- a/lib/oto/commands/command.dart +++ b/lib/oto/commands/command.dart @@ -101,6 +101,7 @@ enum CommandType { GitReset, GitStashPush, GitStashApply, + GitBranch, GitHub, GitHubPullRequestCreate, GitHubPullRequestList, @@ -177,6 +178,7 @@ abstract class Command { CommandType.GitReset: () => GitReset(), CommandType.GitStashPush: () => GitStashPush(), CommandType.GitStashApply: () => GitStashApply(), + CommandType.GitBranch: () => GitBranch(), CommandType.GitHub: () => GitHub(), CommandType.GitHubPullRequestCreate: () => GitHubPullRequestCreate(), CommandType.GitHubPullRequestList: () => GitHubPullRequestList(), diff --git a/lib/oto/commands/git/git.dart b/lib/oto/commands/git/git.dart index f6578eb..0930fa8 100644 --- a/lib/oto/commands/git/git.dart +++ b/lib/oto/commands/git/git.dart @@ -1,3 +1,6 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:dart_framework/utils/system_util.dart'; import 'package:oto_cli/oto/application.dart'; import 'package:oto_cli/oto/commands/command.dart'; @@ -220,3 +223,40 @@ class GitStashApply extends Command { return await completeProcess(process, command, passExitCodes: [1]); } } + +//무시가가능한 에러 무시 +class GitBranch extends Command { + @override + Future execute(DataCommand command) async { + var data = DataGitBranch.fromJson(getParam(command)); + + var shell = StringBuffer('cd ${data.path}'); + shell.write( + ' $and git for-each-ref --format=\'{"ref": "%(refname:short)", "sha": "%(objectname)", "date": "%(committerdate:iso8601)"}\' refs/remotes | jq -s . > branches.json'); + + var process = + await ProcessExecutor.start(shell, logHandler: Application.logWithType); + + var file = File('${data.path}/branches.json'); + var content = file.readAsStringSync(); + final List decoded = jsonDecode(content); + final branches = decoded.map((e) => BranchInfo.fromJson(e)).toList(); + var list = []; + var fixedBranch = ['main', 'master', 'develop']; + var startDate = + DateTime.now().subtract(Duration(days: data.startDay!)).millisecond; + for (var branch in branches) { + var branchName = branch.ref!.replaceFirst('origin/', ''); + if (DateTime.parse(branch.date!).millisecond > startDate) { + list.add(branchName); + } else { + if (fixedBranch.contains(branchName)) { + list.add(branchName); + } + } + } + setProperty(data.setBranches!, list, showPrint: true); + + return await completeProcess(process, command); + } +} diff --git a/lib/oto/data/command_data.dart b/lib/oto/data/command_data.dart index 847683b..297f3a6 100644 --- a/lib/oto/data/command_data.dart +++ b/lib/oto/data/command_data.dart @@ -721,6 +721,35 @@ class DataGitCommit extends DataParam { Map toJson() => _$DataGitCommitToJson(this); } +//GitBranch +@JsonSerializable() +class DataGitBranch extends DataParam { + DataGitBranch(); + + late String? path; + late int? startDay; + late String? setBranches; + + factory DataGitBranch.fromJson(Map json) => + _$DataGitBranchFromJson(json); + @override + Map toJson() => _$DataGitBranchToJson(this); +} + +@JsonSerializable() +class BranchInfo { + BranchInfo(); + + late String? ref; + late String? sha; + late String? date; + + factory BranchInfo.fromJson(Map json) => + _$BranchInfoFromJson(json); + @override + Map toJson() => _$BranchInfoToJson(this); +} + //GitPush @JsonSerializable() class DataGitPush extends DataParam { diff --git a/lib/oto/data/command_data.g.dart b/lib/oto/data/command_data.g.dart index 61465ed..9b9fd9a 100644 --- a/lib/oto/data/command_data.g.dart +++ b/lib/oto/data/command_data.g.dart @@ -106,6 +106,7 @@ const _$CommandTypeEnumMap = { CommandType.GitReset: 'GitReset', CommandType.GitStashPush: 'GitStashPush', CommandType.GitStashApply: 'GitStashApply', + CommandType.GitBranch: 'GitBranch', CommandType.GitHub: 'GitHub', CommandType.GitHubPullRequestCreate: 'GitHubPullRequestCreate', CommandType.GitHubPullRequestList: 'GitHubPullRequestList', @@ -1278,6 +1279,43 @@ Map _$DataGitCommitToJson(DataGitCommit instance) => 'message': instance.message, }; +DataGitBranch _$DataGitBranchFromJson(Map json) => + DataGitBranch() + ..workspace = json['workspace'] as String? + ..passExitCodes = (json['passExitCodes'] as List?) + ?.map((e) => (e as num).toInt()) + .toList() + ..setResult = json['setResult'] as String? + ..setExitCode = json['setExitCode'] as String? + ..showPrint = json['showPrint'] as bool? + ..path = json['path'] as String? + ..startDay = (json['startDay'] as num?)?.toInt() + ..setBranches = json['setBranches'] as String?; + +Map _$DataGitBranchToJson(DataGitBranch instance) => + { + 'workspace': instance.workspace, + 'passExitCodes': instance.passExitCodes, + 'setResult': instance.setResult, + 'setExitCode': instance.setExitCode, + 'showPrint': instance.showPrint, + 'path': instance.path, + 'startDay': instance.startDay, + 'setBranches': instance.setBranches, + }; + +BranchInfo _$BranchInfoFromJson(Map json) => BranchInfo() + ..ref = json['ref'] as String? + ..sha = json['sha'] as String? + ..date = json['date'] as String?; + +Map _$BranchInfoToJson(BranchInfo instance) => + { + 'ref': instance.ref, + 'sha': instance.sha, + 'date': instance.date, + }; + DataGitPush _$DataGitPushFromJson(Map json) => DataGitPush() ..workspace = json['workspace'] as String? ..passExitCodes = (json['passExitCodes'] as List?) From dee87b8e94d08c6b89726633adf7c07e071b301f Mon Sep 17 00:00:00 2001 From: leedongmyung Date: Fri, 22 Aug 2025 08:50:19 +0900 Subject: [PATCH 05/11] update git branch --- assets/pipeline-test2.yaml | 2 +- lib/oto/commands/git/git.dart | 29 +++++++++++++++++++++-------- pubspec.yaml | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/assets/pipeline-test2.yaml b/assets/pipeline-test2.yaml index 0afa70f..16bd843 100644 --- a/assets/pipeline-test2.yaml +++ b/assets/pipeline-test2.yaml @@ -41,7 +41,7 @@ commands: id: branch param: path: /Users/toki/works/lgup-mcs-aos - startDay: 20 + startDay: 60 setBranches: <@property.value> ### Modify param diff --git a/lib/oto/commands/git/git.dart b/lib/oto/commands/git/git.dart index 0930fa8..ada0311 100644 --- a/lib/oto/commands/git/git.dart +++ b/lib/oto/commands/git/git.dart @@ -241,21 +241,34 @@ class GitBranch extends Command { var content = file.readAsStringSync(); final List decoded = jsonDecode(content); final branches = decoded.map((e) => BranchInfo.fromJson(e)).toList(); - var list = []; + var features = []; + var releases = []; var fixedBranch = ['main', 'master', 'develop']; - var startDate = - DateTime.now().subtract(Duration(days: data.startDay!)).millisecond; + var existBranch = []; + var excludeBranch = ['origin']; + var startDate = DateTime.now().subtract(Duration(days: data.startDay!)); for (var branch in branches) { var branchName = branch.ref!.replaceFirst('origin/', ''); - if (DateTime.parse(branch.date!).millisecond > startDate) { - list.add(branchName); - } else { + if (!excludeBranch.contains(branchName)) { if (fixedBranch.contains(branchName)) { - list.add(branchName); + existBranch.add(branchName); + } else if (DateTime.parse(branch.date!) + .toUtc() + .difference(startDate) + .inSeconds > + 0) { + if (branchName.startsWith('release')) { + releases.add(branchName); + } else { + features.add(branchName); + } } } } - setProperty(data.setBranches!, list, showPrint: true); + existBranch.sort(); + existBranch.addAll(releases); + existBranch.addAll(features); + setProperty(data.setBranches!, existBranch, showPrint: true); return await completeProcess(process, command); } diff --git a/pubspec.yaml b/pubspec.yaml index 082232b..40f8e3d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,7 +23,7 @@ dependencies: xml: ^6.6.1 dev_dependencies: - lints: ^5.0.0 + lints: ^6.0.0 test: ^1.24.9 build_runner: ^2.1.4 json_serializable: ^6.0.1 From 9f25377514c23037fa91bfb8ad9ac0ab439f8db9 Mon Sep 17 00:00:00 2001 From: leedongmyung Date: Fri, 22 Aug 2025 11:47:11 +0900 Subject: [PATCH 06/11] set-value add object type --- assets/pipeline-test2.yaml | 77 +++++++++++++++++++++---- lib/oto/commands/command.dart | 3 + lib/oto/commands/util/set_value.dart | 86 ++++++++++------------------ lib/oto/data/command_data.dart | 2 + lib/oto/data/command_data.g.dart | 4 +- 5 files changed, 103 insertions(+), 69 deletions(-) diff --git a/assets/pipeline-test2.yaml b/assets/pipeline-test2.yaml index 16bd843..50aa5c6 100644 --- a/assets/pipeline-test2.yaml +++ b/assets/pipeline-test2.yaml @@ -1,28 +1,81 @@ --- property: workspace: . - value: - - test1 - - test2 - - test3 - - test4 + os: + - aos + - ios + configAOS: + - C:/Jenkins/jobs/mcs-aos + - C:/Jenkins/jobs/mcs-aos-lt + configiOS: + - C:/Jenkins/jobs/mcs-ios + - C:/Jenkins/jobs/mcs-ios-lt pipeline: id: main workflow: - - exe: read - - exe: branch - - exe: param-modify - - exe: write + - foreach: + iterator: + setValue: <@property.osValue> + on-do: + - if: + condition-string: == aos + on-true: + - exe: set-aos + on-false: + - exe: set-ios + - exe: print + - foreach: + iterator: + setValue: <@property.configValue> + on-do: + - exe: print-config + - exe: read + - exe: branch + - exe: param-modify + # - exe: write + + + commands: +### Set aos +- command: SetValue + id: set-aos + param: + values-string: + repository: C:/works/oto_cli + values-object: + configs: + +### Set ios +- command: SetValue + id: set-ios + param: + values-string: + repository: C:/works/dart_framework + values-object: + configs: + +### Test print +- command: Print + id: print + param: + message: Repository - + +### Test print +- command: Print + id: print-config + param: + message: Config - + ### Strings Read - command: FileRead id: read param: showPrint: false - path: /assets/config.xml + path: setContent: <@property.content> ### Replace @@ -40,7 +93,7 @@ commands: - command: GitBranch id: branch param: - path: /Users/toki/works/lgup-mcs-aos + path: startDay: 60 setBranches: <@property.value> @@ -57,5 +110,5 @@ commands: - command: FileWrite id: write param: - path: /assets/config.xml + path: content: \ No newline at end of file diff --git a/lib/oto/commands/command.dart b/lib/oto/commands/command.dart index 0d113b4..ca3288d 100644 --- a/lib/oto/commands/command.dart +++ b/lib/oto/commands/command.dart @@ -267,6 +267,9 @@ abstract class Command { static Future setPropertyValue(String tag, dynamic value, {bool? showPrint}) async { var match = regSetEx.firstMatch(tag); + if (match == null) { + throw Exception('Please put the correct value. (ex: <@property.value>)'); + } tag = match!.group(2)!; if (tag.startsWith('property')) { var key = tag.replaceFirst('property.', ''); diff --git a/lib/oto/commands/util/set_value.dart b/lib/oto/commands/util/set_value.dart index 13481ac..633b685 100644 --- a/lib/oto/commands/util/set_value.dart +++ b/lib/oto/commands/util/set_value.dart @@ -8,28 +8,19 @@ class SetValueCommand extends Command { Future execute(DataCommand command) async { var data = DataSetValue.fromJson(getParam(command)); - if(data.values_bool != null) - { - for(var pair in data.values_bool!.entries) - { + if (data.values_bool != null) { + for (var pair in data.values_bool!.entries) { bool value = false; - if(pair.value is bool) - { + if (pair.value is bool) { value = pair.value; - } - else if(pair.value is String) - { + } else if (pair.value is String) { var resultTag = replaceSingleTag(pair.value); - if(resultTag is String) - { + if (resultTag is String) { var toLow = resultTag.toLowerCase(); - if(toLow == 'true' || toLow == 'false') - { + if (toLow == 'true' || toLow == 'false') { value = toLow == 'true'; } - } - else if(resultTag is bool) - { + } else if (resultTag is bool) { value = resultTag; } } @@ -37,28 +28,18 @@ class SetValueCommand extends Command { } } - if(data.values_float != null) - { - for(var pair in data.values_float!.entries) - { + if (data.values_float != null) { + for (var pair in data.values_float!.entries) { double value = 0; - if(pair.value is double) - { + if (pair.value is double) { value = pair.value; - } - else if(pair.value is String) - { + } else if (pair.value is String) { var resultTag = replaceSingleTag(pair.value); - if(resultTag is String) - { + if (resultTag is String) { value = double.parse(resultTag); - } - else if(resultTag is double) - { + } else if (resultTag is double) { value = resultTag; - } - else if(resultTag is int) - { + } else if (resultTag is int) { value = resultTag + 0.0; } } @@ -66,28 +47,18 @@ class SetValueCommand extends Command { } } - if(data.values_int != null) - { - for(var pair in data.values_int!.entries) - { + if (data.values_int != null) { + for (var pair in data.values_int!.entries) { var value = 0; - if(pair.value is int) - { + if (pair.value is int) { value = pair.value; - } - else if(pair.value is String) - { + } else if (pair.value is String) { var resultTag = replaceSingleTag(pair.value); - if(resultTag is String) - { + if (resultTag is String) { value = int.parse(resultTag); - } - else if(resultTag is int) - { + } else if (resultTag is int) { value = resultTag; - } - else if(resultTag is double) - { + } else if (resultTag is double) { value = resultTag.round(); } } @@ -95,10 +66,14 @@ class SetValueCommand extends Command { } } - if(data.values_string != null) - { - for(var pair in data.values_string!.entries) - { + if (data.values_string != null) { + for (var pair in data.values_string!.entries) { + await setProperty(getTag(pair.key), pair.value); + } + } + + if (data.values_object != null) { + for (var pair in data.values_object!.entries) { await setProperty(getTag(pair.key), pair.value); } } @@ -106,8 +81,7 @@ class SetValueCommand extends Command { return complete(0, command); } - String getTag(String key) - { + String getTag(String key) { return '<@property.$key>'; } } diff --git a/lib/oto/data/command_data.dart b/lib/oto/data/command_data.dart index 297f3a6..26ad931 100644 --- a/lib/oto/data/command_data.dart +++ b/lib/oto/data/command_data.dart @@ -110,6 +110,8 @@ class DataSetValue extends DataParam { late Map? values_string; @JsonKey(name: 'values-bool') late Map? values_bool; + @JsonKey(name: 'values-object') + late Map? values_object; factory DataSetValue.fromJson(Map json) => _$DataSetValueFromJson(json); diff --git a/lib/oto/data/command_data.g.dart b/lib/oto/data/command_data.g.dart index 9b9fd9a..d7411e9 100644 --- a/lib/oto/data/command_data.g.dart +++ b/lib/oto/data/command_data.g.dart @@ -196,7 +196,8 @@ DataSetValue _$DataSetValueFromJson(Map json) => DataSetValue() ..values_int = json['values-int'] as Map? ..values_float = json['values-float'] as Map? ..values_string = json['values-string'] as Map? - ..values_bool = json['values-bool'] as Map?; + ..values_bool = json['values-bool'] as Map? + ..values_object = json['values-object'] as Map?; Map _$DataSetValueToJson(DataSetValue instance) => { @@ -209,6 +210,7 @@ Map _$DataSetValueToJson(DataSetValue instance) => 'values-float': instance.values_float, 'values-string': instance.values_string, 'values-bool': instance.values_bool, + 'values-object': instance.values_object, }; DataAppDataCreator _$DataAppDataCreatorFromJson(Map json) => From 3fffaa576d137385f943e8b78f1937c08f4bd8ee Mon Sep 17 00:00:00 2001 From: leedongmyung Date: Fri, 22 Aug 2025 13:05:45 +0900 Subject: [PATCH 07/11] add file backup --- lib/oto/commands/file/file.dart | 14 +++++++++++++- lib/oto/data/command_data.dart | 1 + lib/oto/data/command_data.g.dart | 4 +++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/oto/commands/file/file.dart b/lib/oto/commands/file/file.dart index a9f86f9..466423c 100644 --- a/lib/oto/commands/file/file.dart +++ b/lib/oto/commands/file/file.dart @@ -27,7 +27,19 @@ class FileWrite extends Command { Future execute(DataCommand command) async { var data = DataFileWrite.fromJson(getParam(command)); var file = File(data.path); - if (file.existsSync()) file.deleteSync(); + if (file.existsSync()) { + if (data.backup ?? false) { + var now = DateTime.now(); + var postfix = + '_${now.year}${now.month.toString().padLeft(2, '0')}${now.day.toString().padLeft(2, '0')}${now.hour.toString().padLeft(2, '0')}${now.minute.toString().padLeft(2, '0')}${now.second.toString().padLeft(2, '0')}${now.millisecond}'; + var fileName = path.basenameWithoutExtension(data.path); + var fileExt = path.extension(data.path); + var backupPath = + path.join(path.dirname(data.path), fileName + postfix + fileExt); + await file.copy(backupPath); + } + file.deleteSync(); + } await file.writeAsString(data.content); return complete(0, command); diff --git a/lib/oto/data/command_data.dart b/lib/oto/data/command_data.dart index 26ad931..31c5bab 100644 --- a/lib/oto/data/command_data.dart +++ b/lib/oto/data/command_data.dart @@ -518,6 +518,7 @@ class DataFileWrite extends DataParam { late String path; late String content; + late bool? backup; factory DataFileWrite.fromJson(Map json) => _$DataFileWriteFromJson(json); diff --git a/lib/oto/data/command_data.g.dart b/lib/oto/data/command_data.g.dart index d7411e9..5a984d3 100644 --- a/lib/oto/data/command_data.g.dart +++ b/lib/oto/data/command_data.g.dart @@ -914,7 +914,8 @@ DataFileWrite _$DataFileWriteFromJson(Map json) => ..setExitCode = json['setExitCode'] as String? ..showPrint = json['showPrint'] as bool? ..path = json['path'] as String - ..content = json['content'] as String; + ..content = json['content'] as String + ..backup = json['backup'] as bool?; Map _$DataFileWriteToJson(DataFileWrite instance) => { @@ -925,6 +926,7 @@ Map _$DataFileWriteToJson(DataFileWrite instance) => 'showPrint': instance.showPrint, 'path': instance.path, 'content': instance.content, + 'backup': instance.backup, }; DataFiles _$DataFilesFromJson(Map json) => DataFiles() From 4a76add71765bf75761bee73605fee6f8c2ff718 Mon Sep 17 00:00:00 2001 From: FE Date: Wed, 3 Sep 2025 09:15:41 +0900 Subject: [PATCH 08/11] =?UTF-8?q?iOS=20=EB=B9=8C=EB=93=9C=EC=8B=9C=20PENDI?= =?UTF-8?q?NG=5FDEVELOPER=5FRELEASE=20=EA=B0=92=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EB=8C=80=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/oto/commands/build/build_ios.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/oto/commands/build/build_ios.dart b/lib/oto/commands/build/build_ios.dart index e10d314..f343d0b 100644 --- a/lib/oto/commands/build/build_ios.dart +++ b/lib/oto/commands/build/build_ios.dart @@ -65,13 +65,16 @@ class BuildiOS extends Command { targetVersion = item['version']; break; } + if (item['state'] == 'PENDING_DEVELOPER_RELEASE') { + targetVersion = incrementVersion(item['version']); + } } break; } } if (targetVersion == null) { throw Exception( - 'Can not find target version when state = PREPARE_FOR_SUBMISSION.'); + 'Can not find target version when state = PREPARE_FOR_SUBMISSION, PENDING_DEVELOPER_RELEASE'); } version = targetVersion; From 46ed6e3828816dd27de46643ff8451387e816936 Mon Sep 17 00:00:00 2001 From: FE Date: Wed, 3 Sep 2025 09:28:00 +0900 Subject: [PATCH 09/11] =?UTF-8?q?flutter=20update=20=EB=A1=9C=20=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/oto/commands/ftp/ftp.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/oto/commands/ftp/ftp.dart b/lib/oto/commands/ftp/ftp.dart index e71f757..24aa909 100644 --- a/lib/oto/commands/ftp/ftp.dart +++ b/lib/oto/commands/ftp/ftp.dart @@ -168,16 +168,16 @@ class FTP { for (var item in list) { FileType? type; switch (item.type) { - case FTPEntryType.DIR: + case FTPEntryType.dir: type = FileType.directory; break; - case FTPEntryType.FILE: + case FTPEntryType.file: type = FileType.file; break; - case FTPEntryType.LINK: + case FTPEntryType.link: // TODO: Handle this case. break; - case FTPEntryType.UNKNOWN: + case FTPEntryType.unknown: // TODO: Handle this case. break; } From d9bf7d35605c0998378162e51b375e5685b9fe8f Mon Sep 17 00:00:00 2001 From: FE Date: Wed, 3 Sep 2025 14:40:55 +0900 Subject: [PATCH 10/11] =?UTF-8?q?ios=20=EB=B9=8C=EB=93=9C=EC=9D=98=20?= =?UTF-8?q?=EC=97=AC=EB=9F=AC=20=EC=83=81=ED=83=9C=EA=B0=92=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EB=8C=80=EC=9D=91=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/oto/commands/build/build_ios.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/oto/commands/build/build_ios.dart b/lib/oto/commands/build/build_ios.dart index f343d0b..14a2a83 100644 --- a/lib/oto/commands/build/build_ios.dart +++ b/lib/oto/commands/build/build_ios.dart @@ -55,9 +55,11 @@ class BuildiOS extends Command { var process = await ProcessExecutor.run(shell); var arr = process.stdout.toString().split('\n'); const result = '[RESULT]: '; + var needIncrementVersionState = ['WAITING_FOR_REVIEW', 'WAITING_FOR_REVIEW', 'IN_REVIEW', 'PENDING_DEVELOPER_RELEASE', 'PENDING_APPLE_RELEASE', 'REPLACED_WITH_NEW_VERSION']; + List jsonArr; for (var item in arr) { if (item.contains(result)) { - var jsonArr = + jsonArr = jsonDecode(item.substring(item.indexOf(result) + result.length)) as List; for (var item in jsonArr) { @@ -65,7 +67,7 @@ class BuildiOS extends Command { targetVersion = item['version']; break; } - if (item['state'] == 'PENDING_DEVELOPER_RELEASE') { + if (needIncrementVersionState.contains(item['state'])) { targetVersion = incrementVersion(item['version']); } } From 81d28e487c7d6ba03f6e69ee3a904542e313ce9c Mon Sep 17 00:00:00 2001 From: FE Date: Wed, 3 Sep 2025 15:55:15 +0900 Subject: [PATCH 11/11] =?UTF-8?q?iost=20testflight=20upload=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/oto/commands/build/testflight_ios.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/oto/commands/build/testflight_ios.dart b/lib/oto/commands/build/testflight_ios.dart index ed68f54..0bd9158 100644 --- a/lib/oto/commands/build/testflight_ios.dart +++ b/lib/oto/commands/build/testflight_ios.dart @@ -17,7 +17,7 @@ class TestflightUpload extends Command { var shell = StringBuffer(); shell.write( - 'FASTLANE_DISABLE_PRECHECK=1 fastlane deliver upload_binary --ipa "$ipaPath" --api_key_path "$apiKeyPath" --force'); + 'FASTLANE_DISABLE_PRECHECK=1 fastlane deliver upload_binary --ipa "$ipaPath" --api_key_path "$apiKeyPath" --force --skip_app_version_update true --run_precheck_before_submit false --skip_metadata true --skip_screenshots true'); var process = await ProcessExecutor.start(shell, workspace: workspace,