Tuesday, December 19, 2023

一層又一層的 protocol

當資料來源的格式有異動時,可以利用 protocol + associatedtype  + extension (如果摸不到 struct 尤其需要,摸得到可以在 struct 內繼承,也還是可以用 extension)

去做深層的 protocol

用來達成透過 protocol 取值,不用判斷 source 為何~



protocol Vendor {

    var venderId: Any { get }

    associatedtype BrandType: Brand

    var brands: [BrandType] { get }

}


protocol Brand {

    var name: String { get }

}



extension BrandA: Brand{}

extension BrandB: Brand{}


extension VenderA: Vendor {

    

    var venderId: Any { self.id }

    typealias BrandType = BrandA

}


extension VenderB: Vendor {

    

    var venderId: Any { return self.id }

    typealias BrandType = BrandB

}



func processVendor<T: Vendor>(_ vendor: T) {

    

    print("Processing vendor with id: \(vendor.venderId)")

    

    for brand in vendor.brands {

        print("Brand name: \(brand.name)")

    }

}

Tuesday, October 24, 2023

民主家庭/權力分析 作業#1

我帶大寶上課,要先去早餐店吃早餐,我讓他就菜單點,他先挑飲料 1,說要豆漿

我知道那個是含糖的,跟他商量說你知道含糖飲料不好,無糖的比較健康喔

他改選鮮奶,冰的,我說溫的啦~他很堅持冰的,我說好吧,那去冰喔,不會有冰塊,他說好。(我的心裡不蘇胡),然後在菜單上用紅色的蠟筆做記號


接著點花生吐司(我心裡又有不蘇湖的感覺),你點了澱粉 2,那蛋白質 3 呢?他說:起司蛋餅!我提示他蛋餅的照片,指著起司蛋餅的文字讓他做記號。

接著點要帶去學校當下午點心 4 的貝果,做好記號後,我說可以在旁邊寫『ㄨㄞˋ』,這樣老闆知道要裝起來讓我們帶走

他寫上外的注音後,接著要寫帶,我說:寫一個字就好了啦~但馬上改口說:喔~好啦,也可以,多練習。
看他他寫好後我說:真漂亮!他說哪有~我說:我的字很醜,不信喔?我寫給你看~

寫完他說:你都沒有按照筆劃~我說:我有啦,只是醜醜的(我有按照筆順,但沒有按照筆劃,我在寫這篇紀錄的時候才知道他當時是對的,我講錯詞了XD)

我畫上我的早餐後,去櫃檯結帳,金額是 236


等餐點的時候,他把忍者裝的帽子戴起來,我好奇問他:可以在學校要戴這個嗎?他回答:我也不知道。我利用空擋跟他討論週末的安排 5 ,他說想跟班上同學去公園玩,我說,好啊~可以用你搜集到的安全超能量表的愛心來兌換,他問為什麼,我說這是獎勵啊~你需要我幫忙聯絡對吧?然後上餐了~他很開心地戳裝在 500cc 手搖飲料杯裡八分滿的鮮乳坊牛奶喝,喝了幾口,花生吐司跟蛋餅裝在盤子上也送來了,他開始徒手吃吐司,我想到他剛剛有用手穿鞋子,我覺得手有點髒,

跟他說:你要用酒精清潔手後拿餐具吃 6 吧~他提醒我有廁所可以洗手,我說好啊~你願意洗的話

結果他只噴了酒精就要徒手拿花生吐司啃,我說:你... 好吧,你的肚子...

然後他吃快一半的花生吐司,就說吃不下了 7。我說:你還有蛋餅沒有動欸~他說真的吃不下了

我想到蛋白質攝取不足的這段字,然後再想到要尊重他的想法,雖然心裡的不蘇胡有很多,我還是壓下去,想著讓他開心的去學校


接著拎著打包起來的早餐陪他走到學校,他特別挑要走另一個路口 8,說是可以多拿走路上課的獎勵貼紙

拿到貼紙後,我陪他走到校門口,在門口的校長看到他笑笑的說:哎呦,蜘蛛人嗎?我跟著微笑,然後他就筆直地走進去了!(咦,就這樣?那個擁抱咧?)我趕緊說掰掰,他才回頭跟我說掰掰

我看到高年級在校門口拎著一袋貼紙,我開口喊他說:你說要多拿貼紙啊!他回答:我手上有啦~


我心裡想著:所以只有一張啊~~~~~~,哪裡多了~~~~

走回家的路上,我在心疼買了一百多塊的早餐(扣除點心跟我的早餐),結果只攝取到幾口牛奶跟花生吐司,剩下這些要讓他當放學後的點心!

結果回家後蛋餅被阿牛吃掉一半,我在換牛奶的容器時沾到咖啡,只好暗自安排要給先生喝了(我不喝牛奶)

原本要留給他的點心剩下半塊的花生吐司,心疼的感覺好像就沒那麼多了,但仔細想想那個點心跟牛奶的 cp 真的很低.... /___\


我記錄到 8 個選擇,屬於『聽我的』,標為紅色屬於『聽小孩的』,標示為藍色
裡面有七項是我提出的問題,有一項是他提出的並決定的,有兩項我不太能確定算是聽誰的。我覺得相比之下,我提了好多問題。


  1. 我影響了飲料的選擇
  2. 他選擇了澱粉
  3. 我提醒蛋白質
  4. 已經是慣例的下午點心
  5. 我提供可能的週末活動
  6. 我影響用餐的方式
  7. 他決定吃飽了
  8. 他決定上學路線

  • 我在想難道是在我提醒蛋白質的時候,他不想吃,卻不跟我說,敷衍我挑了起司蛋餅,才會一口都沒動....?
  • 慣例的下午點心是先前被我影響下的選擇,之後好像就習慣?還是麻痺的這樣選了,也許可以問他有沒有想成別的點心
  • 再次閱讀發現我有影響到用餐的方式
  • 再次閱讀,如果用很嚴格的方式來看,幾乎可以說我有跟他協商怎麼樣算吃飽了...

如果把無法判別的當成『聽我的』,這樣小孩有 37 % 的自由度
如果用很嚴格的標準來評分,小孩只有 20 % 的自由度

Thursday, October 19, 2023

OS level on android / iOS

 



https://developer.apple.com/support/app-store/

Tuesday, October 10, 2023

swiftUI Architecture

https://www.one-tab.com/page/p2POKsuvRvy78QHWU1QgTA

circular slider

https://www.one-tab.com/page/xmTnylosTTuWwrIhjRzQ5Q

Tuesday, September 12, 2023

iOS Architecture

 TCA

https://github.com/pointfreeco/swift-composable-architecture


RIBs

https://github.com/uber/RIBs


SwiftUI + Combine

https://github.com/nalexn/clean-architecture-swiftui

jitpack

 https://jitpack.io/


記得把 package name 換成 gitlab url ~

Wednesday, September 6, 2023

plugins for Jetbrains

  1.  Presentation Assistant

live preview for AppCode



Create a SwiftUI application in AppCode


tools : InjectionIII


licenses : most are MIT, one of the facebook/fishhook is BSD-3-Clause license


PS for commercial use, should avoid GPL & LGPL


Get updated view by "saving files...." (command + S) 

or switch the current window to others to make the IDE auto store the change


sometimes it just updated -.-

Tuesday, September 5, 2023

Launch Screen in SwiftUI

 info plist


https://sarunw.com/posts/launch-screen-using-plist/


 info plist + story board


https://www.appcoda.com/launch-screen-swiftui/


LaunchScreen.storyboard & info plist 同時設定的時候, storyboard 優先


rf:


https://developer.apple.com/documentation/technotes/tn3118-debugging-your-apps-launch-screen


PS: no code can be excuted in this stage...

RF: iOS Launch screen code not running

Thursday, June 29, 2023

Jnkins build to distbute

利用上下游的機制,讓管家先生一口氣編好測試&正式環境的 apk 後,除了各自上傳到 ftp 外,再透過 API 送到 play store alpha 



 



原本同事在一台 mbp 上建好一台 jenkins 包 iOS
但要透過遠端控制,覺得應該可以直連 jenkins web service 會更順暢
找了一下發現這邊可以這樣做:

We want the Jenkins web interface to be accessible from anywhere (not just on the local machine), 
so we’re going to open up the config file:
sudo nano /usr/local/opt/jenkins-lts/homebrew.mxcl.jenkins-lts.plist

Find this line:

<string>--httpListenAddress=127.0.0.1</string>

And change it to:

<string>--httpListenAddress=0.0.0.0</string>


搞定 web service 後就來建 android project
原先有看到 pipeline,寫的 scipt 好像很自由,但還沒參透,先用 project 
之後再續戰 pipeline


設定好 git repo & Execute shell (就是 gradlew 產 apk 那條)
試跑出來成功啦~



但是... apk 咧XD
加上這個

add Build Artifacts feature




就跑出載點啦



其實它在 Workspace 下,就跟 IDE 裡面左邊的 project 那樣點一點就看得到
不過可以有傳送門總是比較方便,你說是吧XD




可以加裝 plugin 使用 Gradle Wrapper, 但下指令可以有更多彈性~




目前的需求是要組出上傳到 ftp server 的 apk link, 透過原本的 gradle 在組擋名的時候
順便組 link 印出來在 console log 上方便複製(懶惰萬歲XD)
(更懶可以再接上 slack)

那接下來就要開放選擇口味,要搭配 Jenkins 的變數傳入 build script

參數列表網址:http://your.domain.here:8080/env-vars.html/

先裝外掛

就可以開外掛啦~










跑之前先確認 commit id


挑好 branch 



挑好口味




跑的時候看 log 確實 check out 對應的 commit id




接下來要處理的是,把 version code 跟 build number 串在一起,不再以日期為準,而是跟著 build number 跑




同時在打包結束後,打好 tag 送上 repo 也是很便利的




BUILD SUCCESSFUL in 2m 56s
39 actionable tasks: 13 executed, 26 up-to-date
Build step 'Invoke Gradle script' changed build result to SUCCESS
Archiving artifacts
The recommended git tool is: NONE
using credential PullinSSHKey
 > git tag -l 1.2.3 # timeout=10
 > git tag -a -f -m 1.2.3 tag by build number 32 1.2.3 # timeout=10
ERROR: Failed to push tag 1.2.3 to origin
hudson.plugins.git.GitException: Could not apply tag 1.2.3
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.tag(CliGitAPIImpl.java:1849)
    ...skip...
    at java.base/java.lang.Thread.run(Thread.java:829)
    Suppressed: hudson.remoting.Channel$CallSiteStackTrace: Remote call to JNLP4-connect connection from localhost/127.0.0.1:49431
        at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1784)
        at hudson.remoting.UserRequest$ExceptionResponse.retrieve(UserRequest.java:356)
        ...skip...
        at hudson.model.ResourceController.execute(ResourceController.java:101)
        at hudson.model.Executor.run(Executor.java:442)
Caused by: hudson.plugins.git.GitException: Command "git tag -a -f -m 1.2.3 tag by build number 32 1.2.3" returned status code 128:
stdout: 
stderr: Committer identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com" 
  git config --global user.name "Your Name" 

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: empty ident name (for <>) not allowed

    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2671)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2601)
    ...skip...
    ... 17 more
Build step 'Git Publisher' marked build as failure
Finished: FAILURE

遇到 git ssh 憑證問題






整組呈現



擴充技能:build by git push

set change log parameter for Google Play



set credentials and apk path in Post-build action


set release track and rollout percentage


set 18n change log


10:31:31 Upload failed: 
10:31:31 - Google Play Android Developer API has not been used in project 544296638860 before or it is disabled. 
Enable it by visiting https://console.developers.google.com/apis/api/androidpublisher.googleapis.com/overview?project=544296638860 
then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
遇到 play api 問題,要先去啟用



還是噴錯

10:43:37 Upload failed: 10:43:37 - The project ID used to call the Google Play Developer API has not been linked in the Google Play Developer Console.
原來是接錯 gcp project ... = =a
按對後就成功啦~

11:47:59 Uploading 1 file(s) with application ID: dbx.******
11:47:59 
11:47:59          APK file: app/build/outputs/apk/pub/release/*****_20220914_vtest.ver.sion_pub_release.apk
11:47:59         File size: 61.34 MB
11:47:59        SHA-1 hash: 2ace634d7202b06671083dc7edd30fcfc08a489c
11:47:59       versionCode: 200701268
11:47:59       versionName: test.ver.sion
11:47:59     minSdkVersion: 21
11:48:26  
11:48:26 Updating release track 'internal':
11:48:26 - Application ID:  dbx.*****
11:48:26 - Version codes:   200701268
11:48:26 - Staged rollout:  0% (draft)
11:48:26 - Update priority: (default)
11:48:26 - Release name:    (default)
11:48:26 - Release notes:   en-GB, zh-TW
11:48:26 
11:48:26 Applying changes to Google Play...
11:48:30 Changes were successfully applied to Google Play

apk shown in App bundle explorer




as draft (0%) in internal release track



release name and release notes in edit release


18n for english release notes in review release


遇到問題

16:10:29 Failed to execute org.gradle.cache.internal.AsyncCacheAccessDecoratedCache$$Lambda$308/0x00000008004b6c40@7ca109ec.
16:10:29 org.gradle.api.UncheckedIOException: Could not add entry '/Users/jenkins/.gradle/caches/transforms-3/c1e8d385c310d60e608cd1b948ce68f4' to cache file-access.bin (/Users/jenkins/.gradle/caches/journal-1/file-access.bin).
16:10:29     at org.gradle.cache.internal.btree.BTreePersistentIndexedCache.put(BTreePersistentIndexedCache.java:162)
16:10:29     at org.gradle.cache.internal.DefaultMultiProcessSafePersistentIndexedCache.lambda$put$1(DefaultMultiProcessSafePersistentIndexedCache.java:67)
16:10:29     at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.doWriteAction(DefaultFileLockManager.java:216)
16:10:29     at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.writeFile(DefaultFileLockManager.java:206)
16:10:29     at org.gradle.cache.internal.DefaultCacheAccess$UnitOfWorkFileAccess.writeFile(DefaultCacheAccess.java:449)
16:10:29     at org.gradle.cache.internal.DefaultMultiProcessSafePersistentIndexedCache.put(DefaultMultiProcessSafePersistentIndexedCache.java:67)
16:10:29     at org.gradle.cache.internal.AsyncCacheAccessDecoratedCache.lambda$putLater$1(AsyncCacheAccessDecoratedCache.java:56)
16:10:29     at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
16:10:29     at org.gradle.cache.internal.CacheAccessWorker$2.run(CacheAccessWorker.java:185)
16:10:29     at org.gradle.internal.Factories$1.create(Factories.java:31)
16:10:29     at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:220)
16:10:29     at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:201)
16:10:29     at org.gradle.cache.internal.CacheAccessWorker.flushOperations(CacheAccessWorker.java:175)
16:10:29     at org.gradle.cache.internal.CacheAccessWorker.run(CacheAccessWorker.java:145)
16:10:29     at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
16:10:29     at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
16:10:29     at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16:10:29     at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
16:10:29     at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
16:10:29     at java.base/java.lang.Thread.run(Thread.java:829)

清掉快取
rm -r $HOME/.gradle/caches/
java.nio.file.NoSuchFileException: /Users/jenkins/.gradle/caches/transforms-3

need to remove the whole .gradle folder to get it working
rm -rf ~/.gradle

遇到 oom

java.lang.OutOfMemoryError: Java heap space

同時跑兩個 job 引起的




加記憶體

JAVA_OPTS="-XX:MaxPermSize=2048M" 

但還是太吃力




JAVA_OPTS="-Xmx3072m" 
 13:42:26 The root cause java.lang.OutOfMemoryError was thrown at: unknown
13:42:26 Java heap space: KtProperty:

改成上下游的方式

上游 log

下游 log

可以順利跑完兩個啦(雖然不是同時XD)



除了 Jenkins 還有其他玩具可以試試看:

  • GitLab
  • TeamCity
  • fastlane
















Wednesday, June 28, 2023

Gitlab maitainance

 很久沒碰 linux,基本上還是現學現賣居多

靠著 s / l 大法慢慢 trial & error 


主要參考資訊

Pre-upgrade and post-upgrade checks

Upgrade paths

                

以前會提供像這樣個表格,讓你看某個版號要怎麼『按部就班』升級到最新版


現在變得比較簡單,用文字描述了



// incase it doesn't work after upgrade, just restart it 

sudo gitlab-ctl restart


// to the newest version

sudo yum install gitlab-ce


基本手順是:

sudo gitlab-rake gitlab:env:info // check version

// another way to check version : https://your.domain.here/api/v4/version

sudo gitlab-rake gitlab:check // upgrade status check

sudo gitlab-rake gitlab:doctor:secrets // upgrade status check

yum --showduplicates list gitlab-ce // list available updates
// 下列擇一

sudo yum install gitlab-ce // update to latest version if you've always up to date

sudo yum install gitlab-ce-15.9.4-ce.0.el7 // update speicific version

//非必要,遇到太久 500 可以使用

sudo gitlab-ctl restart 



如果遇到 web service 掛掉,也許可以參考這裡

我在這邊學到 sanitized gitlab.rb 

grep -v '^#\|^$' /etc/gitlab.rb


找到之前幫同事嘗試設定 gitlab page 時

參數設定錯了,先 mark 後升級就恢復正常XD


如果遇到系統明明亮紅燈,跟你說要盡快更新


(admin 登入,有緊急更新的話會一直鬼打牆提醒你XD)



如果直接走安裝最新更新,遇到更新檔有問題是,會吐 502 

然後列出更新檔案,看不到最新的版號




有可能是提供更新的服務壞掉了



                          




修好會寄信通知~



升級後遇到這兩個,通常等一兩分 or restart service 會好,

如果沒有... 就檢查 gitlab.rb 看哪邊怪怪的XD




升級成功的時候會有個小圖案,在 terminal 裡面看到這個很像過關動畫,很開心XD



如果失敗可以往回翻一下 log, error 會噴紅字,很貼心提供你指令直接修復XD



升級中搜集到的畫面,好可愛XD




升級完要健康檢查一下





有次遇到 cpu 超高


dbus-daemon high cpu usage

就算把 gitlab 停掉,還是很 high


找不到更新檔
改檢查更新

更新 dbus.x86_64

重開機後就乖了~