[TIL][makefile] make file 進階用法 (Secondary Expansion)

問題敘述 我有下列的服務要透過 make file 來編譯 Dockerfile ,由於那些服務有版本的區別,而且不同的版本都需要同時存在. 也就是說 app:v1 跟 app:v2 必需要同時能存在,並且要能夠讓 make file 能夠支援新的版本 app:v3 的產生. 舉例來說,我之後只要輸入 make build-images 就要能夠自動跑出 app1-v1, app1-v2, app2-v1 並且能夠根據這些 build target 自動 build 相關的 docker image build app1 v1 Dockerfile v2 Dockerfile app2 v1 Dockerfile 如何得到 build target 首先我們要能搜集所有的 build targets ,透過一系列的 build target 再來跑相關的 make process. BUILD_DOCKERFILES := $(sort $(wildcard build/*/*/Dockerfile)) 這一段是找到所有具有 Dockerfile 的檔案.. 在這裡會找出… build/app1/v1/Dockerfile build/app1/v2/Dockerfile build/app2/v1/Dockerfile 這時候我們要做一點小處理,要去除 Dockerfile 這個不需要的檔案名稱.這個要透過上一篇提過的 % 來處理. 快速講解一下,下面的例子是說,不論何種字串只要是 xxxx/Dockerfile 都會被取代成 xxxx BUILD_DIRS := $(patsubst %/Dockerfile,%,$(BUILD_DOCKERFILES)) 這時候 BUILD_DIRS 就會轉換為: build/app1/v1 build/app1/v2 build/app2/v1 再來,我們要整理成 build-app-v1 的格式,這個可以透過 subst 來替代 BUILD_APP_VER := $(subst /,-,$(BUILD_DIRS)) 這樣就會得到: build-app1-v1 build-app1-v2 build-app2-v1 最後,我們要其轉換成 app1-v1, app1-v2 … 一樣透過 % 來替換 BUILD_NAMES := $(patsubst build-%,%,$(BUILD_APP_VER)) 最後我們要得到 build target 希望是 build-app1-v1, build-app1-v2… BUILD_TARGETS := $(addprefix notebook-image-,$(BUILD_NAMES)) 這樣就可以得到我們要的結果. 最後整理一下… BUILD_DOCKERFILES := $(sort $(wildcard build/*/*/Dockerfile)) BUILD_DIRS := $(patsubst %/Dockerfile,%,$(BUILD_DOCKERFILES)) BUILD_APP_VER := $(subst /,-,$(BUILD_DIRS)) BUILD_NAMES := $(patsubst build-%,%,$(BUILD_APP_VER)) BUILD_TARGETS := $(addprefix notebook-image-,$(BUILD_TARGETS)) 開始撰寫 build target 本體要做的事情 這時候因為我們得到 build-app1-v1, build-app1-v2 跟 build-app2-v1....
繼續閱讀

[TIL][shell] Switch from fish to zsh

摘要 當初玩 Mac 從一開始很痛苦的 bash ,到了換了好像超好用的 fish (friendly interactive shell) 可以參考一下 [TIL] Note: about change your shell from bash to fish . 當然,之後也有想要換到 zsh 參考這篇 [TIL] Change fish shell theme with nerd font 但是又遲遲不敢換. 不過今天總算發生了重要的問題. 公司一堆 Operation 相關的 Makefile 竟然完全死在 fish 上面. GG 只好認真來換… zsh 基本的 zsh 配備 當然要先看看這篇我認為超適合當 zsh (還有 oh-my-zsh) 的推坑文超簡單!十分鐘打造漂亮又好用的 zsh command line 環境 基本流程就依照這篇就好,補充一些: iterm2 換字型到 Sauce Code Pro Nerd Font Complete 如果你字體大小是在 12 很容易卡死(hang) . 就得要清除所有 iterm2 的設定 · 建議要先切換字體大小到 14 再換字型. defaults delete com.googlecode.iterm2 iTerm2 本身對於各個 Shell 都有 integration ,可以讓你使用起來更方便. curl -L https://iterm2.com/shell_integration/zsh \ -o ~/.iterm2_shell_integration.zsh source ~/.iterm2_shell_integration.zsh POWERLEVEL9K 雖然很棒,但是不是太多功能需要.這裡列出我使用的功能 export TERM="xterm-256color" POWERLEVEL9K_MODE='nerdfont-complete' ZSH_THEME="powerlevel9k/powerlevel9k" # command line 左邊想顯示的內容 POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir vcs) # command line 右邊想顯示的內容 POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(kubecontext) POWERLEVEL9K_SHORTEN_DIR_LENGTH=1 POWERLEVEL9K_SHORTEN_DELIMITER="" POWERLEVEL9K_SHORTEN_STRATEGY="truncate_from_right" 進階設定 這裡介紹幾個好用 plugin ,可以幫助大家快速(無痛?)切換到 zsh plugins=( #git 可以有一些快捷鍵 ggl ... git # 自動補全 zsh-completions gitfast # 解壓縮用 extract # z: 可以快速並且支援模糊切換目錄 ex: z docume <tab> z # 讓你喚回 fish 漂亮的顏色 zsh-syntax-highlighting # 就像 fish 一樣,打到一半自動建議你 zsh-autosuggestions...
繼續閱讀

[TIL][makefile] 一些常用的 Makefile 指令整理

摘要 花了一點時間玩了一下 makefile ,有一些字串對應方式與使用方式在不使用 sed 的前提下其實也很方便. 順手整理一下一些常用的案例. 並且也列出一些使用 makefile 在編譯 Dockerfile 的時候經常會用到的範例. 基礎常見語法: wildcard 透過 wildcard 可以擴展找出所有匹配的項目. 找出所有具有 Dockerfile 的目錄(並且依序排列) DOCKERFILE_PATHS := $(sort $(wildcard */Dockerfile)) patsubst 替換字串 常用再換掉路徑,去除路徑.以下紀錄幾個常用的. 取得 Parent Path (ex: a/b/c/d –> a/b/c) PARENT_PATHS := $(patsubst %/,%,$(dir $(CURRENT_PATHS))) nodir 去除所有目錄 這個可以幫你去除所有目錄,剩下檔名. ex: a/b/c/d –> d 取得上一層目錄列表 PARENT_PATH_LIST := $(notdir $(dir $(CURRENT_PATHS))) 這裡也要解釋一下, dir 會取得目錄而已.跟 nodir 剛好相反. 另外, basename 跟 dir 也不同. $(basename a/b/c/d.a) —> d 進階用法 *, % 與$* 跟 $< 這邊講解起來會有點難懂,就用一個案例來講解. $* 會找出所有結果 % 會將前方變數帶給之後用 $< 列出前面的結果 以下用個例子 範例(1) : 找出 Dockerfile 並且編譯 build-image-%: %/Dockerfile $(shell find $* -type f) time docker build \ --tag docker.io/$(YOUR_PROJECT)/%:master \ --file $< \ $(dir $<) 這個會去編譯某個你輸入底下的 Dockerfile . 舉例而言: 你有個目錄 tensorflow/Dockerfile 你就要輸入 make build-image-tensorflow ,他就會自動找出這個 Dockerfile 並且編譯名稱為 $(YOUR_PROJECT)/tensorflow:master 以下透過這個案例解釋每個用法: % 會將前面輸入的,帶到後面.在這裡也就是 tensorflow 帶到第二個與第三個出現%的地方 $< 會列出 shell find $* -type f 結果,也就是列出所有檔案,並且符合 %/Dockerfile 也就是如果你有其他檔案舉例為 tensorflow/README.md 也不會列出. 似乎這樣好像很麻煩? 其實透過前面介紹的基礎常見語法,可以更方便編譯. 範例(2) : 找出所有符合目錄直接帶到以上編譯 #find all docker files DOCKERFILES := $(sort $(wildcard */Dockerfile)) #extract...
繼續閱讀

[TIL][vgo] 對於 Version and Go 相關詳解(part1)

目錄: 對於 Version and Go 相關詳解(part1) 開始實戰 vgo (part2) 摘要 vgo 是 Golang 將在 1.11 提出的新功能.提供著套件的管理與版本的控制. 本篇文章會解釋 vgo (versioning go) 與 dep 在 sub-package的挑選上有什麼不同. 並且解釋出 vgo 如何解決掉大家的問題. 並且在 Go versioning 的準則 (principles) 上, Russ Cox 有列出以下的準則: Compatibility Repeatability Cooperation 接下來,我會整理一下近期學習的經驗.試著讓各位能在這篇文章中了解. Compatibility 這邊講的是套件在開發上的”兼容性”,他也很強調所謂的 “Semantic Import Versioning” . 也就是如同上圖所顯示的部分一樣,任何的產品與套件都應該遵循以上的版本法則. Major version: 具有向後不相容的變動,就要變更. Minor version: 當有新的功能加入,就要變更. Patch version: 只是問題的修復. 在這裡,只要是 Major version 是一樣的話,就不應該產生有任何向後不相容的變動.也建議不要有 API 的版本變動. Repeatability 為了讓每個使用軟體(或是套件)上能夠讓每個人在任何時間都能夠透過相同的程式碼與相同的套件版本來使用. 在 Opening keynote: Go with Versions - GopherConSG 2018 演講的時候 , Russ Cox 曾經提到一個很重要的概念. What is software engineering? Software engineering is what happens to programming when you add time and other programmers. 也就是說 Software Engineering 是經過一段時間的開發,並且是跟其他人一起開發. 所以來說”版本的可重複性”(Repeatability) 就格外的重要. 你必須要在半年後接手開發的人,能夠拿到跟你目前一樣狀態的品質與原始碼. 你也必須要讓其他人不論本地端是否有預裝哪些套件,也要能夠拿到相同的代碼 在提到其他的部分之前,我們得提一下跟 Repeatability 相反的部分. Low-Fidelity Builds Low-Fidelity Builds 這裡解釋一下,何謂 “Low-Fidelity Builds” .並且解釋為何 vgo 能夠達成 High-Fidlity Build. Low-Fidelity Builds (低忠誠度的版本),也就是表示你的版本控管並不嚴謹.使得你的套件在版本變更的時候,會讓你的產品穩定度低下. 假設我們開發套件 A ,裡面使用到 B 與 C 套件.假設 A 必須要使用到 B1.2 與 C1.2 才能正常運作. 範例 1: 使用 go get 當你使用 go get 他會檢查目前 GOPATH 資料夾內是否有相關套件, 條件如下: 當套件存在的時候,他會直接使用該套件(不論版本是否新舊) 當套件不存在的時候,會抓下最新的套件. 問題:...
繼續閱讀

[TIL][GIT] How to correctly separate subdirectories from git repo

Problem If you have big repo, you want to separate it into several small repos. There are two approach you might google it, here is different Subtree git subtree split -P feature_a -b "branchA" It will separate your code, but it will include whole git history. It will slow-down your CI/CD flow if your original repo history is very huge. Filter-Branch which rewrites the repo history picking up only those commits that actually affect the content of a specific subdirectory. (refer to refer 2) git filter-branch --prune-empty --subdirectory-filter SUBDIR -- --all Reference Splitting a subfolder out into a new repository Difference between git filter branch and git subtree? Using Git subtrees for repository separation
繼續閱讀

[Slides] Consistent Hashing: Algorithmic Tradoffs

這幾天閱讀 Damian Gryski 的 blog post “Consistent Hashing: Algorithmic Tradeoffs” 整理出來的投影片 (第一版) 應該會找時間寫寫中文 blog Consistent hashing algorithmic tradeoffs from Evan Lin
繼續閱讀